patch-2.4.9 linux/drivers/video/tdfxfb.c

Next file: linux/fs/Makefile
Previous file: linux/drivers/video/sticore.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.8/linux/drivers/video/tdfxfb.c linux/drivers/video/tdfxfb.c
@@ -19,6 +19,11 @@
  * (proper acceleration, 24 bpp, hardware cursor) and bug fixes by Attila
  * Kesmarki. Thanks guys!
  * 
+ * Voodoo1 and Voodoo2 support aren't relevant to this driver as they
+ * behave very differently from the Voodoo3/4/5. For anyone wanting to
+ * use frame buffer on the Voodoo1/2, see the sstfb driver (which is
+ * located at http://www.sourceforge.net/projects/sstfb).
+ *
  * While I _am_ grateful to 3Dfx for releasing the specs for Banshee,
  * I do wish the next version is a bit more complete. Without the XF86
  * patches I couldn't have gotten even this far... for instance, the
@@ -32,9 +37,6 @@
  * TODO:
  * - support for 16/32 bpp needs fixing (funky bootup penguin)
  * - multihead support (basically need to support an array of fb_infos)
- * - banshee and voodoo3 now supported -- any others? afaik, the original
- *   voodoo was a 3d-only card, so we won't consider that. what about
- *   voodoo2?
  * - support other architectures (PPC, Alpha); does the fact that the VGA
  *   core can be accessed only thru I/O (not memory mapped) complicate
  *   things?
@@ -385,12 +387,6 @@
 			   int kspc, 
 			   int con,
 			   struct fb_info* info);
-static int tdfxfb_ioctl(struct inode* inode, 
-			struct file* file, 
-			u_int cmd,
-			u_long arg, 
-			int con, 
-			struct fb_info* info);
 
 /*
  *  Interface to the low level console driver
@@ -464,6 +460,12 @@
 void tdfxfb_setup(char *options, 
 		  int *ints);
 
+/*
+ * PCI driver prototypes
+ */
+static int tdfxfb_probe(struct pci_dev *pdev, const struct pci_device_id *id);
+static void tdfxfb_remove(struct pci_dev *pdev);
+
 static int currcon = 0;
 
 static struct fb_ops tdfxfb_ops = {
@@ -474,9 +476,30 @@
 	fb_get_cmap:	tdfxfb_get_cmap,
 	fb_set_cmap:	tdfxfb_set_cmap,
 	fb_pan_display:	tdfxfb_pan_display,
-	fb_ioctl:	tdfxfb_ioctl,
 };
 
+static struct pci_device_id tdfxfb_id_table[] __devinitdata = {
+	{ PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_BANSHEE,
+	  PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16,
+	  0xff0000, 0 },
+	{ PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO3,
+	  PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16,
+	  0xff0000, 0 },
+	{ PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO5,
+	  PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16,
+	  0xff0000, 0 },
+	{ 0, }
+};
+
+static struct pci_driver tdfxfb_driver = {
+	name:		"tdfxfb",
+	id_table:	tdfxfb_id_table,
+	probe:		tdfxfb_probe,
+	remove:		tdfxfb_remove,
+};
+
+MODULE_DEVICE_TABLE(pci, tdfxfb_id_table);
+
 struct mode {
   char* name;
   struct fb_var_screeninfo var;
@@ -1865,170 +1888,160 @@
    return 0;
 }
 
-static int tdfxfb_ioctl(struct inode *inode, 
-			struct file *file, 
-			u_int cmd,
-			u_long arg, 
-			int con, 
-			struct fb_info *fb) {
-/* These IOCTLs ar just for testing only... 
-   switch (cmd) {
-    case 0x4680: 
-      nowrap=nopan=0;
-      return 0;
-    case 0x4681:
-      nowrap=nopan=1;
-      return 0;
-   }*/
-   return -EINVAL;
-}
+/**
+ * 	tdfxfb_probe - Device Initializiation
+ * 	
+ * 	@pdev:	PCI Device to initialize
+ * 	@id:	PCI Device ID
+ *
+ * 	Initializes and allocates resources for PCI device @pdev.
+ *
+ */
+static int __devinit tdfxfb_probe(struct pci_dev *pdev,
+				  const struct pci_device_id *id)
+{
+	struct fb_var_screeninfo var;
+	char *name = NULL;
 
-int __init tdfxfb_init(void) {
-  struct pci_dev *pdev = NULL;
-  struct fb_var_screeninfo var;
-  
-  while ((pdev = pci_find_device(PCI_VENDOR_ID_3DFX, PCI_ANY_ID, pdev))) {
-    if(((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY) &&
-       ((pdev->device == PCI_DEVICE_ID_3DFX_BANSHEE) ||
-	(pdev->device == PCI_DEVICE_ID_3DFX_VOODOO3) ||
-	(pdev->device == PCI_DEVICE_ID_3DFX_VOODOO5))) {
-      char *name = NULL;
-
-      fb_info.dev   = pdev->device;
-      switch (pdev->device) {
-      case PCI_DEVICE_ID_3DFX_BANSHEE:
-	fb_info.max_pixclock = BANSHEE_MAX_PIXCLOCK;
-	name = "Banshee";
-	break;
-      case PCI_DEVICE_ID_3DFX_VOODOO3:
-	fb_info.max_pixclock = VOODOO3_MAX_PIXCLOCK;
-	name = "Voodoo3";
-	break;
-      case PCI_DEVICE_ID_3DFX_VOODOO5:
-	fb_info.max_pixclock = VOODOO5_MAX_PIXCLOCK;
-	name = "Voodoo5";
-	break;
-      }
-      fb_info.regbase_phys = pci_resource_start(pdev, 0);
-      fb_info.regbase_size = 1 << 24;
-      fb_info.regbase_virt = ioremap_nocache(fb_info.regbase_phys, 1 << 24);
-      if(!fb_info.regbase_virt) {
-	printk("fb: Can't remap %s register area.\n", name);
-	return -ENXIO;
-      }
+	fb_info.dev = pdev->device;
+	
+	switch (pdev->device) {
+		case PCI_DEVICE_ID_3DFX_BANSHEE:
+			fb_info.max_pixclock = BANSHEE_MAX_PIXCLOCK;
+			name = "Banshee";
+			break;
+		case PCI_DEVICE_ID_3DFX_VOODOO3:
+			fb_info.max_pixclock = VOODOO3_MAX_PIXCLOCK;
+			name = "Voodoo3";
+			break;
+		case PCI_DEVICE_ID_3DFX_VOODOO5:
+			fb_info.max_pixclock = VOODOO5_MAX_PIXCLOCK;
+			name = "Voodoo5";
+			break;
+	}
+	
+	fb_info.regbase_phys = pci_resource_start(pdev, 0);
+	fb_info.regbase_size = 1 << 24;
+	fb_info.regbase_virt = ioremap_nocache(fb_info.regbase_phys, 1 << 24);
+	
+	if (!fb_info.regbase_virt) {
+		printk(KERN_WARNING "fb: Can't remap %s register area.\n", name);
+		return -ENXIO;
+	}
       
-      fb_info.bufbase_phys = pci_resource_start (pdev, 1);
-      if(!(fb_info.bufbase_size = do_lfb_size())) {
-	iounmap(fb_info.regbase_virt);
-	printk("fb: Can't count %s memory.\n", name);
-	return -ENXIO;
-      }
-      fb_info.bufbase_virt = ioremap_nocache(fb_info.bufbase_phys, fb_info.bufbase_size);
-      if(!fb_info.regbase_virt) {
-	printk("fb: Can't remap %s framebuffer.\n", name);
-	iounmap(fb_info.regbase_virt);
-	return -ENXIO;
-      }
+	fb_info.bufbase_phys = pci_resource_start (pdev, 1);
+	
+	if (!(fb_info.bufbase_size = do_lfb_size())) {
+		iounmap(fb_info.regbase_virt);
+		printk(KERN_WARNING "fb: Can't count %s memory.\n", name);
+		return -ENXIO;
+	}
+	
+	fb_info.bufbase_virt = ioremap_nocache(fb_info.bufbase_phys,
+					       fb_info.bufbase_size);
+					       
+	if (!fb_info.regbase_virt) {
+		printk(KERN_WARNING "fb: Can't remap %s framebuffer.\n", name);
+		iounmap(fb_info.regbase_virt);
+		return -ENXIO;
+	}
 
-      fb_info.iobase = pci_resource_start (pdev, 2);
+	fb_info.iobase = pci_resource_start (pdev, 2);
       
-      printk("fb: %s memory = %ldK\n", name, fb_info.bufbase_size >> 10);
+	printk("fb: %s memory = %ldK\n", name, fb_info.bufbase_size >> 10);
 
 #ifdef CONFIG_MTRR
-       if (!nomtrr) {
-          fb_info.mtrr_idx = mtrr_add(fb_info.bufbase_phys, fb_info.bufbase_size,
-	  			      MTRR_TYPE_WRCOMB, 1);
-	    printk("fb: MTRR's  turned on\n");
-       }
+	if (!nomtrr) {
+		fb_info.mtrr_idx = mtrr_add(fb_info.bufbase_phys,
+					    fb_info.bufbase_size,
+					    MTRR_TYPE_WRCOMB, 1);
+		printk(KERN_INFO "fb: MTRR's turned on\n");
+	}
 #endif
 
-      /* clear framebuffer memory */
-      memset_io(fb_info.bufbase_virt, 0, fb_info.bufbase_size);
-      currcon = -1;
-      if (!nohwcursor) tdfxfb_hwcursor_init();
+	/* clear framebuffer memory */
+	memset_io(fb_info.bufbase_virt, 0, fb_info.bufbase_size);
+	currcon = -1;
+
+	if (!nohwcursor)
+		tdfxfb_hwcursor_init();
        
-      init_timer(&fb_info.cursor.timer);
-      fb_info.cursor.timer.function = do_flashcursor; 
-      fb_info.cursor.timer.data = (unsigned long)(&fb_info);
-      fb_info.cursor.state = CM_ERASE;
-      spin_lock_init(&fb_info.DAClock);
+	init_timer(&fb_info.cursor.timer);
+	fb_info.cursor.timer.function = do_flashcursor; 
+	fb_info.cursor.timer.data = (unsigned long)(&fb_info);
+	fb_info.cursor.state = CM_ERASE;
+	spin_lock_init(&fb_info.DAClock);
        
-      strcpy(fb_info.fb_info.modename, "3Dfx "); 
-      strcat(fb_info.fb_info.modename, name);
-      fb_info.fb_info.changevar  = NULL;
-      fb_info.fb_info.node       = -1;
-      fb_info.fb_info.fbops      = &tdfxfb_ops;
-      fb_info.fb_info.disp       = &fb_info.disp;
-      strcpy(fb_info.fb_info.fontname, fontname);
-      fb_info.fb_info.switch_con = &tdfxfb_switch_con;
-      fb_info.fb_info.updatevar  = &tdfxfb_updatevar;
-      fb_info.fb_info.blank      = &tdfxfb_blank;
-      fb_info.fb_info.flags      = FBINFO_FLAG_DEFAULT;
-      
-      memset(&var, 0, sizeof(var));
-      if(!mode_option || 
-	 !fb_find_mode(&var, &fb_info.fb_info, mode_option, NULL, 0, NULL, 8))
-	var = default_mode[0].var;
-      
-      if(noaccel) var.accel_flags &= ~FB_ACCELF_TEXT;
-      else var.accel_flags |= FB_ACCELF_TEXT;
-      
-      if(tdfxfb_decode_var(&var, &fb_info.default_par, &fb_info)) {
-	/* ugh -- can't use the mode from the mode db. (or command line),
-	   so try the default */
-
-	printk("tdfxfb: "
-	       "can't decode the supplied video mode, using default\n");
-
-	var = default_mode[0].var;
-	if(noaccel) var.accel_flags &= ~FB_ACCELF_TEXT;
-	else var.accel_flags |= FB_ACCELF_TEXT;
+	strcpy(fb_info.fb_info.modename, "3Dfx "); 
+	strcat(fb_info.fb_info.modename, name);
+	fb_info.fb_info.changevar  = NULL;
+	fb_info.fb_info.node       = -1;
+	fb_info.fb_info.fbops      = &tdfxfb_ops;
+	fb_info.fb_info.disp       = &fb_info.disp;
+	strcpy(fb_info.fb_info.fontname, fontname);
+	fb_info.fb_info.switch_con = &tdfxfb_switch_con;
+	fb_info.fb_info.updatevar  = &tdfxfb_updatevar;
+	fb_info.fb_info.blank      = &tdfxfb_blank;
+	fb_info.fb_info.flags      = FBINFO_FLAG_DEFAULT;
       
-	if(tdfxfb_decode_var(&var, &fb_info.default_par, &fb_info)) {
-	  /* this is getting really bad!... */
-	  printk("tdfxfb: can't decode default video mode\n");
-	  return -ENXIO;
+	memset(&var, 0, sizeof(var));
+	
+	if (!mode_option || !fb_find_mode(&var, &fb_info.fb_info,
+					  mode_option, NULL, 0, NULL, 8))
+		var = default_mode[0].var;
+
+	noaccel ? (var.accel_flags &= ~FB_ACCELF_TEXT) :
+		  (var.accel_flags |=  FB_ACCELF_TEXT) ;
+
+	if (tdfxfb_decode_var(&var, &fb_info.default_par, &fb_info)) {
+		/* 
+		 * ugh -- can't use the mode from the mode db. (or command
+		 * line), so try the default
+		 */
+
+		printk(KERN_NOTICE "tdfxfb: can't decode the supplied video mode, using default\n");
+
+		var = default_mode[0].var;
+
+		noaccel ? (var.accel_flags &= ~FB_ACCELF_TEXT) :
+			  (var.accel_flags |=  FB_ACCELF_TEXT) ;
+
+		if (tdfxfb_decode_var(&var, &fb_info.default_par, &fb_info)) {
+			/* this is getting really bad!... */
+			printk(KERN_WARNING "tdfxfb: can't decode default video mode\n");
+			return -ENXIO;
+		}
 	}
-      }
-      
-      fb_info.disp.screen_base    = fb_info.bufbase_virt;
-      fb_info.disp.var            = var;
-      
-      if(tdfxfb_set_var(&var, -1, &fb_info.fb_info)) {
-	printk("tdfxfb: can't set default video mode\n");
-	return -ENXIO;
-      }
-      
-      if(register_framebuffer(&fb_info.fb_info) < 0) {
-	printk("tdfxfb: can't register framebuffer\n");
-	return -ENXIO;
-      }
 
-      printk("fb%d: %s frame buffer device\n", 
-	     GET_FB_IDX(fb_info.fb_info.node),
-	     fb_info.fb_info.modename);
+	fb_info.disp.screen_base = fb_info.bufbase_virt;
+	fb_info.disp.var         = var;
       
-      /* FIXME: module cannot be unloaded */
-      /* verify tdfxfb_exit before removing this */
-      MOD_INC_USE_COUNT;
-      
-      return 0;
-    }
-  }
+	if (tdfxfb_set_var(&var, -1, &fb_info.fb_info)) {
+		printk(KERN_WARNING "tdfxfb: can't set default video mode\n");
+		return -ENXIO;
+	}
 
-  /* hmm, no frame suitable buffer found ... */
-  return -ENXIO;
+	if (register_framebuffer(&fb_info.fb_info) < 0) {
+		printk(KERN_WARNING "tdfxfb: can't register framebuffer\n");
+		return -ENXIO;
+	}
+
+	printk(KERN_INFO "fb%d: %s frame buffer device\n", 
+	     GET_FB_IDX(fb_info.fb_info.node), fb_info.fb_info.modename);
+      
+  	return 0;
 }
 
 /**
- *	tdfxfb_exit - Driver cleanup
+ *	tdfxfb_remove - Device removal
+ *
+ * 	@pdev:	PCI Device to cleanup
  *
- *	Releases all resources allocated during the
- *	course of the driver's lifetime.
+ *	Releases all resources allocated during the course of the driver's
+ *	lifetime for the PCI device @pdev.
  *
- *	FIXME - do results of fb_alloc_cmap need disposal?
  */
-static void __exit tdfxfb_exit (void)
+static void __devexit tdfxfb_remove(struct pci_dev *pdev)
 {
 	unregister_framebuffer(&fb_info.fb_info);
 	del_timer_sync(&fb_info.cursor.timer);
@@ -2036,7 +2049,7 @@
 #ifdef CONFIG_MTRR
        if (!nomtrr) {
           mtrr_del(fb_info.mtrr_idx, fb_info.bufbase_phys, fb_info.bufbase_size);
-	    printk("fb: MTRR's  turned off\n");
+	    printk("fb: MTRR's turned off\n");
        }
 #endif
 
@@ -2044,6 +2057,16 @@
 	iounmap(fb_info.bufbase_virt);
 }
 
+int __init tdfxfb_init(void)
+{
+	return pci_module_init(&tdfxfb_driver);
+}
+
+static void __exit tdfxfb_exit(void)
+{
+	pci_unregister_driver(&tdfxfb_driver);
+}
+
 MODULE_AUTHOR("Hannu Mallat <hmallat@cc.hut.fi>");
 MODULE_DESCRIPTION("3Dfx framebuffer device driver");
 
@@ -2212,7 +2235,9 @@
 			    unsigned        transp,
 			    struct fb_info* info) {
    struct fb_info_tdfx* i = (struct fb_info_tdfx*)info;
+#ifdef FBCON_HAS_CFB8   
    u32 rgbcol;
+#endif
    if (regno >= i->current_par.cmap_len) return 1;
    
    i->palette[regno].red    = red;

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)