summary refs log tree commit diff
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2006-01-10 21:31:24 -0800
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-10 21:31:24 -0800
commit05f6ece6f37f987e9de643f6f76e8fb5d5b9e014 (patch)
tree5244e85d0dfb2619b0af4bc80a2c99dd579f79a5 /drivers
parent35d138ae22f826f95f0f8d0285947582ccf4508f (diff)
parent58b6c58caef7a34eab7ec887288fa495696653e7 (diff)
downloadlinux-05f6ece6f37f987e9de643f6f76e8fb5d5b9e014.tar.gz
Merge master.kernel.org:/pub/scm/linux/kernel/git/kyle/parisc-2.6
Diffstat (limited to 'drivers')
-rw-r--r--drivers/parisc/dino.c30
-rw-r--r--drivers/parisc/eisa.c4
-rw-r--r--drivers/parisc/eisa_eeprom.c2
-rw-r--r--drivers/parisc/lasi.c2
-rw-r--r--drivers/parisc/lba_pci.c115
-rw-r--r--drivers/parisc/led.c18
-rw-r--r--drivers/parisc/pdc_stable.c44
-rw-r--r--drivers/parisc/power.c12
-rw-r--r--drivers/parport/Kconfig1
-rw-r--r--drivers/video/stifb.c65
10 files changed, 194 insertions, 99 deletions
diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c
index 5ab75334c579..216d1d859326 100644
--- a/drivers/parisc/dino.c
+++ b/drivers/parisc/dino.c
@@ -83,7 +83,8 @@
 ** bus number for each dino.
 */
 
-#define is_card_dino(id) ((id)->hw_type == HPHW_A_DMA)
+#define is_card_dino(id)	((id)->hw_type == HPHW_A_DMA)
+#define is_cujo(id)		((id)->hversion == 0x682)
 
 #define DINO_IAR0		0x004
 #define DINO_IODC_ADDR		0x008
@@ -124,6 +125,7 @@
 
 #define DINO_IRQS 11		/* bits 0-10 are architected */
 #define DINO_IRR_MASK	0x5ff	/* only 10 bits are implemented */
+#define DINO_LOCAL_IRQS (DINO_IRQS+1)
 
 #define DINO_MASK_IRQ(x)	(1<<(x))
 
@@ -146,7 +148,7 @@ struct dino_device
 	unsigned long		txn_addr; /* EIR addr to generate interrupt */ 
 	u32			txn_data; /* EIR data assign to each dino */ 
 	u32 			imr;	  /* IRQ's which are enabled */ 
-	int			global_irq[12]; /* map IMR bit to global irq */
+	int			global_irq[DINO_LOCAL_IRQS]; /* map IMR bit to global irq */
 #ifdef DINO_DEBUG
 	unsigned int		dino_irr0; /* save most recent IRQ line stat */
 #endif
@@ -297,7 +299,7 @@ struct pci_port_ops dino_port_ops = {
 static void dino_disable_irq(unsigned int irq)
 {
 	struct dino_device *dino_dev = irq_desc[irq].handler_data;
-	int local_irq = gsc_find_local_irq(irq, dino_dev->global_irq, irq);
+	int local_irq = gsc_find_local_irq(irq, dino_dev->global_irq, DINO_LOCAL_IRQS);
 
 	DBG(KERN_WARNING "%s(0x%p, %d)\n", __FUNCTION__, dino_dev, irq);
 
@@ -309,7 +311,7 @@ static void dino_disable_irq(unsigned int irq)
 static void dino_enable_irq(unsigned int irq)
 {
 	struct dino_device *dino_dev = irq_desc[irq].handler_data;
-	int local_irq = gsc_find_local_irq(irq, dino_dev->global_irq, irq);
+	int local_irq = gsc_find_local_irq(irq, dino_dev->global_irq, DINO_LOCAL_IRQS);
 	u32 tmp;
 
 	DBG(KERN_WARNING "%s(0x%p, %d)\n", __FUNCTION__, dino_dev, irq);
@@ -435,6 +437,21 @@ static void dino_choose_irq(struct parisc_device *dev, void *ctrl)
 	dino_assign_irq(dino, irq, &dev->irq);
 }
 
+
+/*
+ * Cirrus 6832 Cardbus reports wrong irq on RDI Tadpole PARISC Laptop (deller@gmx.de)
+ * (the irqs are off-by-one, not sure yet if this is a cirrus, dino-hardware or dino-driver problem...)
+ */
+static void __devinit quirk_cirrus_cardbus(struct pci_dev *dev)
+{
+	u8 new_irq = dev->irq - 1;
+	printk(KERN_INFO "PCI: Cirrus Cardbus IRQ fixup for %s, from %d to %d\n",
+			pci_name(dev), dev->irq, new_irq);
+	dev->irq = new_irq;
+}
+DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_6832, quirk_cirrus_cardbus );
+
+
 static void __init
 dino_bios_init(void)
 {
@@ -666,7 +683,6 @@ dino_fixup_bus(struct pci_bus *bus)
 			printk(KERN_WARNING "Device %s has unassigned IRQ\n", pci_name(dev));
 #endif
 		} else {
-
 			/* Adjust INT_LINE for that busses region */
 			dino_assign_irq(dino_dev, dev->irq, &dev->irq);
 		}
@@ -872,7 +888,7 @@ static int __init dino_common_init(struct parisc_device *dev,
 
 	/* allocate I/O Port resource region */
 	res = &dino_dev->hba.io_space;
-	if (dev->id.hversion == 0x680 || is_card_dino(&dev->id)) {
+	if (!is_cujo(&dev->id)) {
 		res->name = "Dino I/O Port";
 	} else {
 		res->name = "Cujo I/O Port";
@@ -927,7 +943,7 @@ static int __init dino_probe(struct parisc_device *dev)
 	if (is_card_dino(&dev->id)) {
 		version = "3.x (card mode)";
 	} else {
-		if(dev->id.hversion == 0x680) {
+		if (!is_cujo(&dev->id)) {
 			if (dev->id.hversion_rev < 4) {
 				version = dino_vers[dev->id.hversion_rev];
 			}
diff --git a/drivers/parisc/eisa.c b/drivers/parisc/eisa.c
index 6362bf99eff6..3d94d86c1c9f 100644
--- a/drivers/parisc/eisa.c
+++ b/drivers/parisc/eisa.c
@@ -57,7 +57,7 @@
 
 static DEFINE_SPINLOCK(eisa_irq_lock);
 
-void __iomem *eisa_eeprom_addr;
+void __iomem *eisa_eeprom_addr __read_mostly;
 
 /* We can only have one EISA adapter in the system because neither
  * implementation can be flexed.
@@ -141,7 +141,7 @@ static int slave_mask;
  * in the furure. 
  */
 /* irq 13,8,2,1,0 must be edge */
-static unsigned int eisa_irq_level; /* default to edge triggered */
+static unsigned int eisa_irq_level __read_mostly; /* default to edge triggered */
 
 
 /* called by free irq */
diff --git a/drivers/parisc/eisa_eeprom.c b/drivers/parisc/eisa_eeprom.c
index 3a1b4826e5c1..e13aafa70bf5 100644
--- a/drivers/parisc/eisa_eeprom.c
+++ b/drivers/parisc/eisa_eeprom.c
@@ -48,7 +48,7 @@ static loff_t eisa_eeprom_llseek(struct file *file, loff_t offset, int origin )
 }
 
 static ssize_t eisa_eeprom_read(struct file * file,
-			      char *buf, size_t count, loff_t *ppos )
+			      char __user *buf, size_t count, loff_t *ppos )
 {
 	unsigned char *tmp;
 	ssize_t ret;
diff --git a/drivers/parisc/lasi.c b/drivers/parisc/lasi.c
index a8c20396ffbe..2b3ba1dcf332 100644
--- a/drivers/parisc/lasi.c
+++ b/drivers/parisc/lasi.c
@@ -150,7 +150,7 @@ void __init lasi_led_init(unsigned long lasi_hpa)
  * 
  */
 
-static unsigned long lasi_power_off_hpa;
+static unsigned long lasi_power_off_hpa __read_mostly;
 
 static void lasi_power_off(void)
 {
diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c
index 5e495dcbc58a..cbae8c8963fa 100644
--- a/drivers/parisc/lba_pci.c
+++ b/drivers/parisc/lba_pci.c
@@ -167,7 +167,7 @@
 
 /* non-postable I/O port space, densely packed */
 #define LBA_PORT_BASE	(PCI_F_EXTEND | 0xfee00000UL)
-static void __iomem *astro_iop_base;
+static void __iomem *astro_iop_base __read_mostly;
 
 #define ELROY_HVERS	0x782
 #define MERCURY_HVERS	0x783
@@ -695,11 +695,71 @@ lba_claim_dev_resources(struct pci_dev *dev)
 		}
 	}
 }
+
+
+/*
+ * truncate_pat_collision:  Deal with overlaps or outright collisions
+ *			between PAT PDC reported ranges.
+ *
+ *   Broken PA8800 firmware will report lmmio range that
+ *   overlaps with CPU HPA. Just truncate the lmmio range.
+ *
+ *   BEWARE: conflicts with this lmmio range may be an
+ *   elmmio range which is pointing down another rope.
+ *
+ *  FIXME: only deals with one collision per range...theoretically we
+ *  could have several. Supporting more than one collision will get messy.
+ */
+static unsigned long
+truncate_pat_collision(struct resource *root, struct resource *new)
+{
+	unsigned long start = new->start;
+	unsigned long end = new->end;
+	struct resource *tmp = root->child;
+
+	if (end <= start || start < root->start || !tmp)
+		return 0;
+
+	/* find first overlap */
+	while (tmp && tmp->end < start)
+		tmp = tmp->sibling;
+
+	/* no entries overlap */
+	if (!tmp)  return 0;
+
+	/* found one that starts behind the new one
+	** Don't need to do anything.
+	*/
+	if (tmp->start >= end) return 0;
+
+	if (tmp->start <= start) {
+		/* "front" of new one overlaps */
+		new->start = tmp->end + 1;
+
+		if (tmp->end >= end) {
+			/* AACCKK! totally overlaps! drop this range. */
+			return 1;
+		}
+	} 
+
+	if (tmp->end < end ) {
+		/* "end" of new one overlaps */
+		new->end = tmp->start - 1;
+	}
+
+	printk(KERN_WARNING "LBA: Truncating lmmio_space [%lx/%lx] "
+					"to [%lx,%lx]\n",
+			start, end,
+			new->start, new->end );
+
+	return 0;	/* truncation successful */
+}
+
 #else
-#define lba_claim_dev_resources(dev)
+#define lba_claim_dev_resources(dev) do { } while (0)
+#define truncate_pat_collision(r,n)  (0)
 #endif
 
-
 /*
 ** The algorithm is generic code.
 ** But it needs to access local data structures to get the IRQ base.
@@ -747,6 +807,9 @@ lba_fixup_bus(struct pci_bus *bus)
 			lba_dump_res(&ioport_resource, 2);
 			BUG();
 		}
+		/* advertize Host bridge resources to PCI bus */
+		bus->resource[0] = &(ldev->hba.io_space);
+		i = 1;
 
 		if (ldev->hba.elmmio_space.start) {
 			err = request_resource(&iomem_resource,
@@ -760,23 +823,35 @@ lba_fixup_bus(struct pci_bus *bus)
 
 				/* lba_dump_res(&iomem_resource, 2); */
 				/* BUG(); */
-			}
+			} else
+				bus->resource[i++] = &(ldev->hba.elmmio_space);
 		}
 
-		err = request_resource(&iomem_resource, &(ldev->hba.lmmio_space));
-		if (err < 0) {
-			/*   FIXME  overlaps with elmmio will fail here.
-			 *   Need to prune (or disable) the distributed range.
-			 *
-			 *   BEWARE: conflicts with this lmmio range may be
-			 *   elmmio range which is pointing down another rope.
-			 */
-
-			printk("FAILED: lba_fixup_bus() request for "
+
+		/*   Overlaps with elmmio can (and should) fail here.
+		 *   We will prune (or ignore) the distributed range.
+		 *
+		 *   FIXME: SBA code should register all elmmio ranges first.
+		 *      that would take care of elmmio ranges routed
+		 *	to a different rope (already discovered) from
+		 *	getting registered *after* LBA code has already
+		 *	registered it's distributed lmmio range.
+		 */
+		if (truncate_pat_collision(&iomem_resource,
+				       	&(ldev->hba.lmmio_space))) {
+
+			printk(KERN_WARNING "LBA: lmmio_space [%lx/%lx] duplicate!\n",
+					ldev->hba.lmmio_space.start,
+					ldev->hba.lmmio_space.end);
+		} else {
+			err = request_resource(&iomem_resource, &(ldev->hba.lmmio_space));
+			if (err < 0) {
+				printk(KERN_ERR "FAILED: lba_fixup_bus() request for "
 					"lmmio_space [%lx/%lx]\n",
 					ldev->hba.lmmio_space.start,
 					ldev->hba.lmmio_space.end);
-			/* lba_dump_res(&iomem_resource, 2); */
+			} else
+				bus->resource[i++] = &(ldev->hba.lmmio_space);
 		}
 
 #ifdef CONFIG_64BIT
@@ -791,18 +866,10 @@ lba_fixup_bus(struct pci_bus *bus)
 				lba_dump_res(&iomem_resource, 2);
 				BUG();
 			}
+			bus->resource[i++] = &(ldev->hba.gmmio_space);
 		}
 #endif
 
-		/* advertize Host bridge resources to PCI bus */
-		bus->resource[0] = &(ldev->hba.io_space);
-		bus->resource[1] = &(ldev->hba.lmmio_space);
-		i=2;
-		if (ldev->hba.elmmio_space.start)
-			bus->resource[i++] = &(ldev->hba.elmmio_space);
-		if (ldev->hba.gmmio_space.start)
-			bus->resource[i++] = &(ldev->hba.gmmio_space);
-			
 	}
 
 	list_for_each(ln, &bus->devices) {
diff --git a/drivers/parisc/led.c b/drivers/parisc/led.c
index 315be4770d3e..f357d3f60360 100644
--- a/drivers/parisc/led.c
+++ b/drivers/parisc/led.c
@@ -3,7 +3,7 @@
  *
  *      (c) Copyright 2000 Red Hat Software
  *      (c) Copyright 2000 Helge Deller <hdeller@redhat.com>
- *      (c) Copyright 2001-2004 Helge Deller <deller@gmx.de>
+ *      (c) Copyright 2001-2005 Helge Deller <deller@gmx.de>
  *      (c) Copyright 2001 Randolph Chung <tausq@debian.org>
  *
  *      This program is free software; you can redistribute it and/or modify
@@ -56,13 +56,13 @@
    relatively large amount of CPU time, some of the calculations can be 
    turned off with the following variables (controlled via procfs) */
 
-static int led_type = -1;
+static int led_type __read_mostly = -1;
 static unsigned char lastleds;	/* LED state from most recent update */
-static unsigned int led_heartbeat = 1;
-static unsigned int led_diskio = 1;
-static unsigned int led_lanrxtx = 1;
-static char lcd_text[32];
-static char lcd_text_default[32];
+static unsigned int led_heartbeat __read_mostly = 1;
+static unsigned int led_diskio    __read_mostly = 1;
+static unsigned int led_lanrxtx   __read_mostly = 1;
+static char lcd_text[32]          __read_mostly;
+static char lcd_text_default[32]  __read_mostly;
 
 
 static struct workqueue_struct *led_wq;
@@ -108,7 +108,7 @@ struct pdc_chassis_lcd_info_ret_block {
 /* lcd_info is pre-initialized to the values needed to program KittyHawk LCD's 
  * HP seems to have used Sharp/Hitachi HD44780 LCDs most of the time. */
 static struct pdc_chassis_lcd_info_ret_block
-lcd_info __attribute__((aligned(8))) =
+lcd_info __attribute__((aligned(8))) __read_mostly =
 {
 	.model =		DISPLAY_MODEL_LCD,
 	.lcd_width =		16,
@@ -144,7 +144,7 @@ static int start_task(void)
 device_initcall(start_task);
 
 /* ptr to LCD/LED-specific function */
-static void (*led_func_ptr) (unsigned char);
+static void (*led_func_ptr) (unsigned char) __read_mostly;
 
 #ifdef CONFIG_PROC_FS
 static int led_proc_read(char *page, char **start, off_t off, int count, 
diff --git a/drivers/parisc/pdc_stable.c b/drivers/parisc/pdc_stable.c
index 273a74179720..38bdca2fac6b 100644
--- a/drivers/parisc/pdc_stable.c
+++ b/drivers/parisc/pdc_stable.c
@@ -56,7 +56,7 @@
 #include <asm/uaccess.h>
 #include <asm/hardware.h>
 
-#define PDCS_VERSION	"0.09"
+#define PDCS_VERSION	"0.10"
 
 #define PDCS_ADDR_PPRI	0x00
 #define PDCS_ADDR_OSID	0x40
@@ -70,7 +70,7 @@ MODULE_DESCRIPTION("sysfs interface to HP PDC Stable Storage data");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(PDCS_VERSION);
 
-static unsigned long pdcs_size = 0;
+static unsigned long pdcs_size __read_mostly;
 
 /* This struct defines what we need to deal with a parisc pdc path entry */
 struct pdcspath_entry {
@@ -194,7 +194,8 @@ pdcspath_store(struct pdcspath_entry *entry)
 		return -EIO;
 	}
 		
-	entry->ready = 1;
+	/* kobject is already registered */
+	entry->ready = 2;
 	
 	DPRINTK("%s: device: 0x%p\n", __func__, entry->dev);
 	
@@ -653,15 +654,21 @@ pdcs_register_pathentries(void)
 {
 	unsigned short i;
 	struct pdcspath_entry *entry;
+	int err;
 	
 	for (i = 0; (entry = pdcspath_entries[i]); i++) {
 		if (pdcspath_fetch(entry) < 0)
 			continue;
 
-		kobject_set_name(&entry->kobj, "%s", entry->name);
+		if ((err = kobject_set_name(&entry->kobj, "%s", entry->name)))
+			return err;
 		kobj_set_kset_s(entry, paths_subsys);
-		kobject_register(&entry->kobj);
-
+		if ((err = kobject_register(&entry->kobj)))
+			return err;
+		
+		/* kobject is now registered */
+		entry->ready = 2;
+		
 		if (!entry->dev)
 			continue;
 
@@ -675,14 +682,14 @@ pdcs_register_pathentries(void)
 /**
  * pdcs_unregister_pathentries - Routine called when unregistering the module.
  */
-static inline void __exit
+static inline void
 pdcs_unregister_pathentries(void)
 {
 	unsigned short i;
 	struct pdcspath_entry *entry;
 	
 	for (i = 0; (entry = pdcspath_entries[i]); i++)
-		if (entry->ready)
+		if (entry->ready >= 2)
 			kobject_unregister(&entry->kobj);	
 }
 
@@ -704,7 +711,7 @@ pdc_stable_init(void)
 
 	/* For now we'll register the pdc subsys within this driver */
 	if ((rc = firmware_register(&pdc_subsys)))
-		return rc;
+		goto fail_firmreg;
 
 	/* Don't forget the info entry */
 	for (i = 0; (attr = pdcs_subsys_attrs[i]) && !error; i++)
@@ -713,12 +720,25 @@ pdc_stable_init(void)
 	
 	/* register the paths subsys as a subsystem of pdc subsys */
 	kset_set_kset_s(&paths_subsys, pdc_subsys);
-	subsystem_register(&paths_subsys);
+	if ((rc= subsystem_register(&paths_subsys)))
+		goto fail_subsysreg;
 
 	/* now we create all "files" for the paths subsys */
-	pdcs_register_pathentries();
+	if ((rc = pdcs_register_pathentries()))
+		goto fail_pdcsreg;
+
+	return rc;
 	
-	return 0;
+fail_pdcsreg:
+	pdcs_unregister_pathentries();
+	subsystem_unregister(&paths_subsys);
+	
+fail_subsysreg:
+	firmware_unregister(&pdc_subsys);
+	
+fail_firmreg:
+	printk(KERN_INFO "PDC Stable Storage bailing out\n");
+	return rc;
 }
 
 static void __exit
diff --git a/drivers/parisc/power.c b/drivers/parisc/power.c
index ff75e9296df9..54b2b7f20b96 100644
--- a/drivers/parisc/power.c
+++ b/drivers/parisc/power.c
@@ -2,7 +2,7 @@
  * linux/arch/parisc/kernel/power.c
  * HP PARISC soft power switch support driver
  *
- * Copyright (c) 2001-2002 Helge Deller <deller@gmx.de>
+ * Copyright (c) 2001-2005 Helge Deller <deller@gmx.de>
  * All rights reserved.
  *
  *
@@ -102,7 +102,7 @@ static DECLARE_WORK(poweroff_work, deferred_poweroff, NULL);
 
 static void poweroff(void)
 {
-	static int powering_off;
+	static int powering_off __read_mostly;
 
 	if (powering_off)
 		return;
@@ -113,7 +113,7 @@ static void poweroff(void)
 
 
 /* local time-counter for shutdown */
-static int shutdown_timer;
+static int shutdown_timer __read_mostly;
 
 /* check, give feedback and start shutdown after one second */
 static void process_shutdown(void)
@@ -139,7 +139,7 @@ static void process_shutdown(void)
 DECLARE_TASKLET_DISABLED(power_tasklet, NULL, 0);
 
 /* soft power switch enabled/disabled */
-int pwrsw_enabled = 1;
+int pwrsw_enabled __read_mostly = 1;
 
 /*
  * On gecko style machines (e.g. 712/xx and 715/xx) 
@@ -149,7 +149,7 @@ int pwrsw_enabled = 1;
  */
 static void gecko_tasklet_func(unsigned long unused)
 {
-	if (!pwrsw_enabled)
+	if (unlikely(!pwrsw_enabled))
 		return;
 
 	if (__getDIAG(25) & 0x80000000) {
@@ -173,7 +173,7 @@ static void polling_tasklet_func(unsigned long soft_power_reg)
 {
         unsigned long current_status;
 	
-	if (!pwrsw_enabled)
+	if (unlikely(!pwrsw_enabled))
 		return;
 
 	current_status = gsc_readl(soft_power_reg);
diff --git a/drivers/parport/Kconfig b/drivers/parport/Kconfig
index a665951b1586..f605dea57224 100644
--- a/drivers/parport/Kconfig
+++ b/drivers/parport/Kconfig
@@ -121,6 +121,7 @@ config PARPORT_GSC
 	tristate
 	default GSC
 	depends on PARPORT
+	select PARPORT_NOT_PC
 
 config PARPORT_SUNBPP
 	tristate "Sparc hardware (EXPERIMENTAL)"
diff --git a/drivers/video/stifb.c b/drivers/video/stifb.c
index fbb17332afd7..56d71d6e9a72 100644
--- a/drivers/video/stifb.c
+++ b/drivers/video/stifb.c
@@ -3,7 +3,7 @@
  * Low level Frame buffer driver for HP workstations with 
  * STI (standard text interface) video firmware.
  *
- * Copyright (C) 2001-2004 Helge Deller <deller@gmx.de>
+ * Copyright (C) 2001-2005 Helge Deller <deller@gmx.de>
  * Portions Copyright (C) 2001 Thomas Bogendoerfer <tsbogend@alpha.franken.de>
  * 
  * Based on:
@@ -73,16 +73,13 @@
 #include "sticore.h"
 
 /* REGION_BASE(fb_info, index) returns the virtual address for region <index> */
-#ifdef __LP64__
-  #define REGION_BASE(fb_info, index) \
-	(fb_info->sti->glob_cfg->region_ptrs[index] | 0xffffffff00000000)
-#else
-  #define REGION_BASE(fb_info, index) \
-	fb_info->sti->glob_cfg->region_ptrs[index]
-#endif
+#define REGION_BASE(fb_info, index) \
+	F_EXTEND(fb_info->sti->glob_cfg->region_ptrs[index])
 
 #define NGLEDEVDEPROM_CRT_REGION 1
 
+#define NR_PALETTE 256
+
 typedef struct {
 	__s32	video_config_reg;
 	__s32	misc_video_start;
@@ -112,7 +109,7 @@ struct stifb_info {
 	ngle_rom_t ngle_rom;
 	struct sti_struct *sti;
 	int deviceSpecificConfig;
-	u32 pseudo_palette[256];
+	u32 pseudo_palette[16];
 };
 
 static int __initdata stifb_bpp_pref[MAX_STI_ROMS];
@@ -352,10 +349,10 @@ ARTIST_ENABLE_DISABLE_DISPLAY(struct stifb_info *fb, int enable)
 #define IS_888_DEVICE(fb) \
 	(!(IS_24_DEVICE(fb)))
 
-#define GET_FIFO_SLOTS(fb, cnt, numslots)			\
-{	while (cnt < numslots) 					\
+#define GET_FIFO_SLOTS(fb, cnt, numslots)	\
+{	while (cnt < numslots) 			\
 		cnt = READ_WORD(fb, REG_34);	\
-	cnt -= numslots;					\
+	cnt -= numslots;			\
 }
 
 #define	    IndexedDcd	0	/* Pixel data is indexed (pseudo) color */
@@ -995,7 +992,7 @@ stifb_setcolreg(u_int regno, u_int red, u_int green,
 	struct stifb_info *fb = (struct stifb_info *) info;
 	u32 color;
 
-	if (regno >= 256)  /* no. of hw registers */
+	if (regno >= NR_PALETTE)
 		return 1;
 
 	red   >>= 8;
@@ -1005,8 +1002,8 @@ stifb_setcolreg(u_int regno, u_int red, u_int green,
 	DEBUG_OFF();
 
 	START_IMAGE_COLORMAP_ACCESS(fb);
-	
-	if (fb->info.var.grayscale) {
+
+	if (unlikely(fb->info.var.grayscale)) {
 		/* gray = 0.30*R + 0.59*G + 0.11*B */
 		color = ((red * 77) +
 			 (green * 151) +
@@ -1017,17 +1014,17 @@ stifb_setcolreg(u_int regno, u_int red, u_int green,
 			 (blue));
 	}
 
-	if (info->var.bits_per_pixel == 32) {
-		((u32 *)(info->pseudo_palette))[regno] =
-			(red   << info->var.red.offset)   |
-			(green << info->var.green.offset) |
-			(blue  << info->var.blue.offset);
-	} else {
-		((u32 *)(info->pseudo_palette))[regno] = regno;
+	if (fb->info.fix.visual == FB_VISUAL_DIRECTCOLOR) {
+		struct fb_var_screeninfo *var = &fb->info.var;
+		if (regno < 16)
+			((u32 *)fb->info.pseudo_palette)[regno] =
+				regno << var->red.offset |
+				regno << var->green.offset |
+				regno << var->blue.offset;
 	}
 
 	WRITE_IMAGE_COLOR(fb, regno, color);
-	
+
 	if (fb->id == S9000_ID_HCRX) {
 		NgleLutBltCtl lutBltCtl;
 
@@ -1066,9 +1063,9 @@ stifb_blank(int blank_mode, struct fb_info *info)
 	case S9000_ID_HCRX:
 		HYPER_ENABLE_DISABLE_DISPLAY(fb, enable);
 		break;
-	case S9000_ID_A1659A:;	/* fall through */
-	case S9000_ID_TIMBER:;
-	case CRX24_OVERLAY_PLANES:;
+	case S9000_ID_A1659A:	/* fall through */
+	case S9000_ID_TIMBER:
+	case CRX24_OVERLAY_PLANES:
 	default:
 		ENABLE_DISABLE_DISPLAY(fb, enable);
 		break;
@@ -1250,12 +1247,10 @@ stifb_init_fb(struct sti_struct *sti, int bpp_pref)
 		memset(&fb->ngle_rom, 0, sizeof(fb->ngle_rom));
 		if ((fb->sti->regions_phys[0] & 0xfc000000) ==
 		    (fb->sti->regions_phys[2] & 0xfc000000))
-			sti_rom_address = fb->sti->regions_phys[0];
+			sti_rom_address = F_EXTEND(fb->sti->regions_phys[0]);
 		else
-			sti_rom_address = fb->sti->regions_phys[1];
-#ifdef __LP64__
-	        sti_rom_address |= 0xffffffff00000000;
-#endif
+			sti_rom_address = F_EXTEND(fb->sti->regions_phys[1]);
+
 		fb->deviceSpecificConfig = gsc_readl(sti_rom_address);
 		if (IS_24_DEVICE(fb)) {
 			if (bpp_pref == 8 || bpp_pref == 32)
@@ -1315,7 +1310,7 @@ stifb_init_fb(struct sti_struct *sti, int bpp_pref)
 		break;
 	    case 32:
 		fix->type = FB_TYPE_PACKED_PIXELS;
-		fix->visual = FB_VISUAL_TRUECOLOR;
+		fix->visual = FB_VISUAL_DIRECTCOLOR;
 		var->red.length = var->green.length = var->blue.length = var->transp.length = 8;
 		var->blue.offset = 0;
 		var->green.offset = 8;
@@ -1337,7 +1332,7 @@ stifb_init_fb(struct sti_struct *sti, int bpp_pref)
 	info->pseudo_palette = &fb->pseudo_palette;
 
 	/* This has to been done !!! */
-	fb_alloc_cmap(&info->cmap, 256, 0);
+	fb_alloc_cmap(&info->cmap, NR_PALETTE, 0);
 	stifb_init_display(fb);
 
 	if (!request_mem_region(fix->smem_start, fix->smem_len, "stifb fb")) {
@@ -1488,7 +1483,3 @@ module_exit(stifb_cleanup);
 MODULE_AUTHOR("Helge Deller <deller@gmx.de>, Thomas Bogendoerfer <tsbogend@alpha.franken.de>");
 MODULE_DESCRIPTION("Framebuffer driver for HP's NGLE series graphics cards in HP PARISC machines");
 MODULE_LICENSE("GPL v2");
-
-MODULE_PARM(bpp, "i");
-MODULE_PARM_DESC(mem, "Bits per pixel (default: 8)");
-