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

📄 savagefb_driver.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 4 页
字号:
	else		par->display_type = DISP_CRT;	/* Check LCD panel parrmation */	if (par->display_type == DISP_LCD) {		unsigned char cr6b = VGArCR( 0x6b, par);		int panelX = (VGArSEQ (0x61, par) +			      ((VGArSEQ (0x66, par) & 0x02) << 7) + 1) * 8;		int panelY = (VGArSEQ (0x69, par) +			      ((VGArSEQ (0x6e, par) & 0x70) << 4) + 1);		char * sTechnology = "Unknown";		/* OK, I admit it.  I don't know how to limit the max dot clock		 * for LCD panels of various sizes.  I thought I copied the		 * formula from the BIOS, but many users have parrmed me of		 * my folly.		 *		 * Instead, I'll abandon any attempt to automatically limit the		 * clock, and add an LCDClock option to XF86Config.  Some day,		 * I should come back to this.		 */		enum ACTIVE_DISPLAYS { /* These are the bits in CR6B */			ActiveCRT = 0x01,			ActiveLCD = 0x02,			ActiveTV = 0x04,			ActiveCRT2 = 0x20,			ActiveDUO = 0x80		};		if ((VGArSEQ (0x39, par) & 0x03) == 0) {			sTechnology = "TFT";		} else if ((VGArSEQ (0x30, par) & 0x01) == 0) {			sTechnology = "DSTN";		} else 	{			sTechnology = "STN";		}		printk (KERN_INFO "savagefb: %dx%d %s LCD panel detected %s\n",			panelX, panelY, sTechnology,			cr6b & ActiveLCD ? "and active" : "but not active");		if( cr6b & ActiveLCD ) 	{			/*			 * If the LCD is active and panel expansion is enabled,			 * we probably want to kill the HW cursor.			 */			printk (KERN_INFO "savagefb: Limiting video mode to "				"%dx%d\n", panelX, panelY );			par->SavagePanelWidth = panelX;			par->SavagePanelHeight = panelY;		} else			par->display_type = DISP_CRT;	}	savage_get_default_par (par);	if( S3_SAVAGE4_SERIES(par->chip) ) {		/*		 * The Savage4 and ProSavage have COB coherency bugs which		 * render the buffer useless.  We disable it.		 */		par->cob_index = 2;		par->cob_size = 0x8000 << par->cob_index;		par->cob_offset = videoRambytes;	} else {		/* We use 128kB for the COB on all chips. */		par->cob_index  = 7;		par->cob_size   = 0x400 << par->cob_index;		par->cob_offset = videoRambytes - par->cob_size;	}	return videoRambytes;}static int __devinit savage_init_fb_info (struct fb_info *info,					  struct pci_dev *dev,					  const struct pci_device_id *id){	struct savagefb_par *par = (struct savagefb_par *)info->par;	int err = 0;	par->pcidev  = dev;	info->fix.type	   = FB_TYPE_PACKED_PIXELS;	info->fix.type_aux	   = 0;	info->fix.ypanstep	   = 1;	info->fix.ywrapstep   = 0;	info->fix.accel       = id->driver_data;	switch (info->fix.accel) {	case FB_ACCEL_SUPERSAVAGE:		par->chip = S3_SUPERSAVAGE;		snprintf (info->fix.id, 16, "SuperSavage");		break;	case FB_ACCEL_SAVAGE4:		par->chip = S3_SAVAGE4;		snprintf (info->fix.id, 16, "Savage4");		break;	case FB_ACCEL_SAVAGE3D:		par->chip = S3_SAVAGE3D;		snprintf (info->fix.id, 16, "Savage3D");		break;	case FB_ACCEL_SAVAGE3D_MV:		par->chip = S3_SAVAGE3D;		snprintf (info->fix.id, 16, "Savage3D-MV");		break;	case FB_ACCEL_SAVAGE2000:		par->chip = S3_SAVAGE2000;		snprintf (info->fix.id, 16, "Savage2000");		break;	case FB_ACCEL_SAVAGE_MX_MV:		par->chip = S3_SAVAGE_MX;		snprintf (info->fix.id, 16, "Savage/MX-MV");		break;	case FB_ACCEL_SAVAGE_MX:		par->chip = S3_SAVAGE_MX;		snprintf (info->fix.id, 16, "Savage/MX");		break;	case FB_ACCEL_SAVAGE_IX_MV:		par->chip = S3_SAVAGE_MX;		snprintf (info->fix.id, 16, "Savage/IX-MV");		break;	case FB_ACCEL_SAVAGE_IX:		par->chip = S3_SAVAGE_MX;		snprintf (info->fix.id, 16, "Savage/IX");		break;	case FB_ACCEL_PROSAVAGE_PM:		par->chip = S3_PROSAVAGE;		snprintf (info->fix.id, 16, "ProSavagePM");		break;	case FB_ACCEL_PROSAVAGE_KM:		par->chip = S3_PROSAVAGE;		snprintf (info->fix.id, 16, "ProSavageKM");		break;	case FB_ACCEL_S3TWISTER_P:		par->chip = S3_PROSAVAGE;		snprintf (info->fix.id, 16, "TwisterP");		break;	case FB_ACCEL_S3TWISTER_K:		par->chip = S3_PROSAVAGE;		snprintf (info->fix.id, 16, "TwisterK");		break;	case FB_ACCEL_PROSAVAGE_DDR:		par->chip = S3_PROSAVAGE;		snprintf (info->fix.id, 16, "ProSavageDDR");		break;	case FB_ACCEL_PROSAVAGE_DDRK:		par->chip = S3_PROSAVAGE;		snprintf (info->fix.id, 16, "ProSavage8");		break;	}	if (S3_SAVAGE3D_SERIES(par->chip)) {		par->SavageWaitIdle = savage3D_waitidle;		par->SavageWaitFifo = savage3D_waitfifo;	} else if (S3_SAVAGE4_SERIES(par->chip) ||		   S3_SUPERSAVAGE == par->chip) {		par->SavageWaitIdle = savage4_waitidle;		par->SavageWaitFifo = savage4_waitfifo;	} else {		par->SavageWaitIdle = savage2000_waitidle;		par->SavageWaitFifo = savage2000_waitfifo;	}	info->var.nonstd      = 0;	info->var.activate    = FB_ACTIVATE_NOW;	info->var.width       = -1;	info->var.height      = -1;	info->var.accel_flags = 0;	info->fbops          = &savagefb_ops;	info->flags          = FBINFO_DEFAULT |		               FBINFO_HWACCEL_YPAN |		               FBINFO_HWACCEL_XPAN;	info->pseudo_palette = par->pseudo_palette;#if defined(CONFIG_FB_SAVAGE_ACCEL)	/* FIFO size + padding for commands */	info->pixmap.addr = kmalloc(8*1024, GFP_KERNEL);	err = -ENOMEM;	if (info->pixmap.addr) {		memset(info->pixmap.addr, 0, 8*1024);		info->pixmap.size = 8*1024;		info->pixmap.scan_align = 4;		info->pixmap.buf_align = 4;		info->pixmap.access_align = 32;		err = fb_alloc_cmap (&info->cmap, NR_PALETTE, 0);		if (!err)		info->flags |= FBINFO_HWACCEL_COPYAREA |	                       FBINFO_HWACCEL_FILLRECT |		               FBINFO_HWACCEL_IMAGEBLIT;	}#endif	return err;}/* --------------------------------------------------------------------- */static int __devinit savagefb_probe (struct pci_dev* dev,				     const struct pci_device_id* id){	struct fb_info *info;	struct savagefb_par *par;	u_int h_sync, v_sync;	int err, lpitch;	int video_len;	DBG("savagefb_probe");	SavagePrintRegs();	info = framebuffer_alloc(sizeof(struct savagefb_par), &dev->dev);	if (!info)		return -ENOMEM;	par = info->par;	err = pci_enable_device(dev);	if (err)		goto failed_enable;	if ((err = pci_request_regions(dev, "savagefb"))) {		printk(KERN_ERR "cannot request PCI regions\n");		goto failed_enable;	}	err = -ENOMEM;	if ((err = savage_init_fb_info(info, dev, id)))		goto failed_init;	err = savage_map_mmio(info);	if (err)		goto failed_mmio;	video_len = savage_init_hw(par);	/* FIXME: cant be negative */	if (video_len < 0) {		err = video_len;		goto failed_mmio;	}	err = savage_map_video(info, video_len);	if (err)		goto failed_video;	INIT_LIST_HEAD(&info->modelist);#if defined(CONFIG_FB_SAVAGE_I2C)	savagefb_create_i2c_busses(info);	savagefb_probe_i2c_connector(info, &par->edid);	kfree(par->edid);	fb_edid_to_monspecs(par->edid, &info->monspecs);	fb_videomode_to_modelist(info->monspecs.modedb,				 info->monspecs.modedb_len,				 &info->modelist);#endif	info->var = savagefb_var800x600x8;	if (mode_option) {		fb_find_mode(&info->var, info, mode_option,			     info->monspecs.modedb, info->monspecs.modedb_len,			     NULL, 8);	} else if (info->monspecs.modedb != NULL) {		struct fb_videomode *modedb;		modedb = fb_find_best_display(&info->monspecs,					      &info->modelist);		savage_update_var(&info->var, modedb);	}	/* maximize virtual vertical length */	lpitch = info->var.xres_virtual*((info->var.bits_per_pixel + 7) >> 3);	info->var.yres_virtual = info->fix.smem_len/lpitch;	if (info->var.yres_virtual < info->var.yres)		goto failed;#if defined(CONFIG_FB_SAVAGE_ACCEL)	/*	 * The clipping coordinates are masked with 0xFFF, so limit our	 * virtual resolutions to these sizes.	 */	if (info->var.yres_virtual > 0x1000)		info->var.yres_virtual = 0x1000;	if (info->var.xres_virtual > 0x1000)		info->var.xres_virtual = 0x1000;#endif	savagefb_check_var(&info->var, info);	savagefb_set_fix(info);	/*	 * 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 / info->var.pixclock;	h_sync = h_sync * 512 / (info->var.xres + info->var.left_margin +				 info->var.right_margin +				 info->var.hsync_len);	v_sync = h_sync / (info->var.yres + info->var.upper_margin +			   info->var.lower_margin + info->var.vsync_len);	printk(KERN_INFO "savagefb v" SAVAGEFB_VERSION ": "	       "%dkB VRAM, using %dx%d, %d.%03dkHz, %dHz\n",	       info->fix.smem_len >> 10,	       info->var.xres, info->var.yres,	       h_sync / 1000, h_sync % 1000, v_sync);	fb_destroy_modedb(info->monspecs.modedb);	info->monspecs.modedb = NULL;	err = register_framebuffer (info);	if (err < 0)		goto failed;	printk (KERN_INFO "fb: S3 %s frame buffer device\n",		info->fix.id);	/*	 * Our driver data	 */	pci_set_drvdata(dev, info);	return 0; failed:#ifdef CONFIG_FB_SAVAGE_I2C	savagefb_delete_i2c_busses(info);#endif	fb_alloc_cmap (&info->cmap, 0, 0);	savage_unmap_video(info); failed_video:	savage_unmap_mmio (info); failed_mmio:	kfree(info->pixmap.addr); failed_init:	pci_release_regions(dev); failed_enable:	framebuffer_release(info);	return err;}static void __devexit savagefb_remove (struct pci_dev *dev){	struct fb_info *info =		(struct fb_info *)pci_get_drvdata(dev);	DBG("savagefb_remove");	if (info) {		/*		 * If unregister_framebuffer fails, then		 * we will be leaving hooks that could cause		 * oopsen laying around.		 */		if (unregister_framebuffer (info))			printk (KERN_WARNING "savagefb: danger danger! "				"Oopsen imminent!\n");#ifdef CONFIG_FB_SAVAGE_I2C		savagefb_delete_i2c_busses(info);#endif		fb_alloc_cmap (&info->cmap, 0, 0);		savage_unmap_video (info);		savage_unmap_mmio (info);		kfree(info->pixmap.addr);		pci_release_regions(dev);		framebuffer_release(info);		/*		 * Ensure that the driver data is no longer		 * valid.		 */		pci_set_drvdata(dev, NULL);	}}static int savagefb_suspend (struct pci_dev* dev, pm_message_t state){	struct fb_info *info =		(struct fb_info *)pci_get_drvdata(dev);	struct savagefb_par *par = (struct savagefb_par *)info->par;	DBG("savagefb_suspend");	par->pm_state = state.event;	/*	 * For PM_EVENT_FREEZE, do not power down so the console	 * can remain active.	 */	if (state.event == PM_EVENT_FREEZE) {		dev->dev.power.power_state = state;		return 0;	}	acquire_console_sem();	fb_set_suspend(info, 1);	if (info->fbops->fb_sync)		info->fbops->fb_sync(info);	savagefb_blank(FB_BLANK_POWERDOWN, info);	savage_disable_mmio(par);	pci_save_state(dev);	pci_disable_device(dev);	pci_set_power_state(dev, pci_choose_state(dev, state));	release_console_sem();	return 0;}static int savagefb_resume (struct pci_dev* dev){	struct fb_info *info =		(struct fb_info *)pci_get_drvdata(dev);	struct savagefb_par *par = (struct savagefb_par *)info->par;	int cur_state = par->pm_state;	DBG("savage_resume");	par->pm_state = PM_EVENT_ON;	/*	 * The adapter was not powered down coming back from a	 * PM_EVENT_FREEZE.	 */	if (cur_state == PM_EVENT_FREEZE) {		pci_set_power_state(dev, PCI_D0);		return 0;	}	acquire_console_sem();	pci_set_power_state(dev, PCI_D0);	pci_restore_state(dev);	if(pci_enable_device(dev))		DBG("err");	pci_set_master(dev);	savage_enable_mmio(par);	savage_init_hw(par);	savagefb_set_par (info);	savagefb_blank(FB_BLANK_UNBLANK, info);	fb_set_suspend (info, 0);	release_console_sem();	return 0;}static struct pci_device_id savagefb_devices[] __devinitdata = {	{PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_MX128,	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},	{PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_MX64,	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},	{PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_MX64C,	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},	{PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_IX128SDR,	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},	{PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_IX128DDR,	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},	{PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_IX64SDR,	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},	{PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_IX64DDR,	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},	{PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_IXCSDR,	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},	{PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_IXCDDR,	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},	{PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE4,	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SAVAGE4},	{PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE3D,	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SAVAGE3D},	{PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE3D_MV,	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SAVAGE3D_MV},	{PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE2000,	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SAVAGE2000},	{PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE_MX_MV,	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SAVAGE_MX_MV},	{PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE_MX,	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SAVAGE_MX},	{PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE_IX_MV,	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SAVAGE_IX_MV},	{PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE_IX,	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SAVAGE_IX},	{PCI_VENDOR_ID_S3, PCI_CHIP_PROSAVAGE_PM,	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_PROSAVAGE_PM},	{PCI_VENDOR_ID_S3, PCI_CHIP_PROSAVAGE_KM,	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_PROSAVAGE_KM},	{PCI_VENDOR_ID_S3, PCI_CHIP_S3TWISTER_P,	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_S3TWISTER_P},	{PCI_VENDOR_ID_S3, PCI_CHIP_S3TWISTER_K,	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_S3TWISTER_K},	{PCI_VENDOR_ID_S3, PCI_CHIP_PROSAVAGE_DDR,	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_PROSAVAGE_DDR},	{PCI_VENDOR_ID_S3, PCI_CHIP_PROSAVAGE_DDRK,	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_PROSAVAGE_DDRK},	{0, 0, 0, 0, 0, 0, 0}};MODULE_DEVICE_TABLE(pci, savagefb_devices);static struct pci_driver savagefb_driver = {	.name =     "savagefb",	.id_table = savagefb_devices,	.probe =    savagefb_probe,	.suspend =  savagefb_suspend,	.resume =   savagefb_resume,	.remove =   __devexit_p(savagefb_remove)};/* **************************** exit-time only **************************** */static void __exit savage_done (void){	DBG("savage_done");	pci_unregister_driver (&savagefb_driver);}/* ************************* init in-kernel code ************************** */static int __init savagefb_setup(char *options){#ifndef MODULE	char *this_opt;	if (!options || !*options)		return 0;	while ((this_opt = strsep(&options, ",")) != NULL) {		mode_option = this_opt;	}#endif /* !MODULE */	return 0;}static int __init savagefb_init(void){	char *option;	DBG("savagefb_init");	if (fb_get_options("savagefb", &option))		return -ENODEV;	savagefb_setup(option);	return pci_register_driver (&savagefb_driver);}module_init(savagefb_init);module_exit(savage_done);module_param(mode_option, charp, 0);MODULE_PARM_DESC(mode_option, "Specify initial video mode");

⌨️ 快捷键说明

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