Merge git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
diff --git a/Documentation/input/appletouch.txt b/Documentation/input/appletouch.txt
index b48d11d..4f7c633 100644
--- a/Documentation/input/appletouch.txt
+++ b/Documentation/input/appletouch.txt
@@ -3,7 +3,7 @@
 	Copyright (C) 2005 Stelian Pop <stelian@popies.net>
 
 appletouch is a Linux kernel driver for the USB touchpad found on post
-February 2005 Apple Alu Powerbooks.
+February 2005 and October 2005 Apple Aluminium Powerbooks.
 
 This driver is derived from Johannes Berg's appletrackpad driver[1], but it has
 been improved in some areas:
@@ -13,7 +13,8 @@
 
 Credits go to Johannes Berg for reverse-engineering the touchpad protocol,
 Frank Arnold for further improvements, and Alex Harper for some additional
-information about the inner workings of the touchpad sensors.
+information about the inner workings of the touchpad sensors. Michael
+Hanselmann added support for the October 2005 models.
 
 Usage:
 ------
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index a1e660e..f7490a015 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -146,6 +146,7 @@
 }
 
 #ifdef CONFIG_COMPAT
+
 struct input_event_compat {
 	struct compat_timeval time;
 	__u16 type;
@@ -165,22 +166,80 @@
 #  define COMPAT_TEST test_thread_flag(TIF_32BIT)
 #endif
 
-static ssize_t evdev_write_compat(struct file * file, const char __user * buffer, size_t count, loff_t *ppos)
+static inline size_t evdev_event_size(void)
 {
-	struct evdev_list *list = file->private_data;
-	struct input_event_compat event;
-	int retval = 0;
+	return COMPAT_TEST ?
+		sizeof(struct input_event_compat) : sizeof(struct input_event);
+}
 
-	while (retval < count) {
-		if (copy_from_user(&event, buffer + retval, sizeof(struct input_event_compat)))
+static int evdev_event_from_user(const char __user *buffer, struct input_event *event)
+{
+	if (COMPAT_TEST) {
+		struct input_event_compat compat_event;
+
+		if (copy_from_user(&compat_event, buffer, sizeof(struct input_event_compat)))
 			return -EFAULT;
-		input_event(list->evdev->handle.dev, event.type, event.code, event.value);
-		retval += sizeof(struct input_event_compat);
+
+		event->time.tv_sec = compat_event.time.tv_sec;
+		event->time.tv_usec = compat_event.time.tv_usec;
+		event->type = compat_event.type;
+		event->code = compat_event.code;
+		event->value = compat_event.value;
+
+	} else {
+		if (copy_from_user(event, buffer, sizeof(struct input_event)))
+			return -EFAULT;
 	}
 
-	return retval;
+	return 0;
 }
-#endif
+
+static int evdev_event_to_user(char __user *buffer, const struct input_event *event)
+{
+	if (COMPAT_TEST) {
+		struct input_event_compat compat_event;
+
+		compat_event.time.tv_sec = event->time.tv_sec;
+		compat_event.time.tv_usec = event->time.tv_usec;
+		compat_event.type = event->type;
+		compat_event.code = event->code;
+		compat_event.value = event->value;
+
+		if (copy_to_user(buffer, &compat_event, sizeof(struct input_event_compat)))
+			return -EFAULT;
+
+	} else {
+		if (copy_to_user(buffer, event, sizeof(struct input_event)))
+			return -EFAULT;
+	}
+
+	return 0;
+}
+
+#else
+
+static inline size_t evdev_event_size(void)
+{
+	return sizeof(struct input_event);
+}
+
+static int evdev_event_from_user(const char __user *buffer, struct input_event *event)
+{
+	if (copy_from_user(event, buffer, sizeof(struct input_event)))
+		return -EFAULT;
+
+	return 0;
+}
+
+static int evdev_event_to_user(char __user *buffer, const struct input_event *event)
+{
+	if (copy_to_user(buffer, event, sizeof(struct input_event)))
+		return -EFAULT;
+
+	return 0;
+}
+
+#endif /* CONFIG_COMPAT */
 
 static ssize_t evdev_write(struct file * file, const char __user * buffer, size_t count, loff_t *ppos)
 {
@@ -188,75 +247,26 @@
 	struct input_event event;
 	int retval = 0;
 
-	if (!list->evdev->exist) return -ENODEV;
-
-#ifdef CONFIG_COMPAT
-	if (COMPAT_TEST)
-		return evdev_write_compat(file, buffer, count, ppos);
-#endif
-
-	while (retval < count) {
-
-		if (copy_from_user(&event, buffer + retval, sizeof(struct input_event)))
-			return -EFAULT;
-		input_event(list->evdev->handle.dev, event.type, event.code, event.value);
-		retval += sizeof(struct input_event);
-	}
-
-	return retval;
-}
-
-#ifdef CONFIG_COMPAT
-static ssize_t evdev_read_compat(struct file * file, char __user * buffer, size_t count, loff_t *ppos)
-{
-	struct evdev_list *list = file->private_data;
-	int retval;
-
-	if (count < sizeof(struct input_event_compat))
-		return -EINVAL;
-
-	if (list->head == list->tail && list->evdev->exist && (file->f_flags & O_NONBLOCK))
-		return -EAGAIN;
-
-	retval = wait_event_interruptible(list->evdev->wait,
-		list->head != list->tail || (!list->evdev->exist));
-
-	if (retval)
-		return retval;
-
 	if (!list->evdev->exist)
 		return -ENODEV;
 
-	while (list->head != list->tail && retval + sizeof(struct input_event_compat) <= count) {
-		struct input_event *event = (struct input_event *) list->buffer + list->tail;
-		struct input_event_compat event_compat;
-		event_compat.time.tv_sec = event->time.tv_sec;
-		event_compat.time.tv_usec = event->time.tv_usec;
-		event_compat.type = event->type;
-		event_compat.code = event->code;
-		event_compat.value = event->value;
+	while (retval < count) {
 
-		if (copy_to_user(buffer + retval, &event_compat,
-			sizeof(struct input_event_compat))) return -EFAULT;
-		list->tail = (list->tail + 1) & (EVDEV_BUFFER_SIZE - 1);
-		retval += sizeof(struct input_event_compat);
+		if (evdev_event_from_user(buffer + retval, &event))
+			return -EFAULT;
+		input_event(list->evdev->handle.dev, event.type, event.code, event.value);
+		retval += evdev_event_size();
 	}
 
 	return retval;
 }
-#endif
 
 static ssize_t evdev_read(struct file * file, char __user * buffer, size_t count, loff_t *ppos)
 {
 	struct evdev_list *list = file->private_data;
 	int retval;
 
-#ifdef CONFIG_COMPAT
-	if (COMPAT_TEST)
-		return evdev_read_compat(file, buffer, count, ppos);
-#endif
-
-	if (count < sizeof(struct input_event))
+	if (count < evdev_event_size())
 		return -EINVAL;
 
 	if (list->head == list->tail && list->evdev->exist && (file->f_flags & O_NONBLOCK))
@@ -271,11 +281,15 @@
 	if (!list->evdev->exist)
 		return -ENODEV;
 
-	while (list->head != list->tail && retval + sizeof(struct input_event) <= count) {
-		if (copy_to_user(buffer + retval, list->buffer + list->tail,
-			sizeof(struct input_event))) return -EFAULT;
+	while (list->head != list->tail && retval + evdev_event_size() <= count) {
+
+		struct input_event *event = (struct input_event *) list->buffer + list->tail;
+
+		if (evdev_event_to_user(buffer + retval, event))
+			return -EFAULT;
+
 		list->tail = (list->tail + 1) & (EVDEV_BUFFER_SIZE - 1);
-		retval += sizeof(struct input_event);
+		retval += evdev_event_size();
 	}
 
 	return retval;
@@ -290,17 +304,95 @@
 		(list->evdev->exist ? 0 : (POLLHUP | POLLERR));
 }
 
-static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+#ifdef CONFIG_COMPAT
+
+#define BITS_PER_LONG_COMPAT (sizeof(compat_long_t) * 8)
+#define NBITS_COMPAT(x) ((((x) - 1) / BITS_PER_LONG_COMPAT) + 1)
+
+#ifdef __BIG_ENDIAN
+static int bits_to_user(unsigned long *bits, unsigned int maxbit,
+			unsigned int maxlen, void __user *p, int compat)
+{
+	int len, i;
+
+	if (compat) {
+		len = NBITS_COMPAT(maxbit) * sizeof(compat_long_t);
+		if (len < maxlen)
+			len = maxlen;
+
+		for (i = 0; i < len / sizeof(compat_long_t); i++)
+			if (copy_to_user((compat_long_t __user *) p + i,
+					 (compat_long_t *) bits +
+						i + 1 - ((i % 2) << 1),
+					 sizeof(compat_long_t)))
+				return -EFAULT;
+	} else {
+		len = NBITS(maxbit) * sizeof(long);
+		if (len > maxlen)
+			len = maxlen;
+
+		if (copy_to_user(p, bits, len))
+			return -EFAULT;
+	}
+
+	return len;
+}
+#else
+static int bits_to_user(unsigned long *bits, unsigned int maxbit,
+			unsigned int maxlen, void __user *p, int compat)
+{
+	int len = compat ?
+			NBITS_COMPAT(maxbit) * sizeof(compat_long_t) :
+			NBITS(maxbit) * sizeof(long);
+
+	if (len > maxlen)
+		len = maxlen;
+
+	return copy_to_user(p, bits, len) ? -EFAULT : len;
+}
+#endif /* __BIG_ENDIAN */
+
+#else
+
+static int bits_to_user(unsigned long *bits, unsigned int maxbit,
+			unsigned int maxlen, void __user *p, int compat)
+{
+	int len = NBITS(maxbit) * sizeof(long);
+
+	if (len > maxlen)
+		len = maxlen;
+
+	return copy_to_user(p, bits, len) ? -EFAULT : len;
+}
+
+#endif /* CONFIG_COMPAT */
+
+static int str_to_user(const char *str, unsigned int maxlen, void __user *p)
+{
+	int len;
+
+	if (!str)
+		return -ENOENT;
+
+	len = strlen(str) + 1;
+	if (len > maxlen)
+		len = maxlen;
+
+	return copy_to_user(p, str, len) ? -EFAULT : len;
+}
+
+static long evdev_ioctl_handler(struct file *file, unsigned int cmd,
+				void __user *p, int compat_mode)
 {
 	struct evdev_list *list = file->private_data;
 	struct evdev *evdev = list->evdev;
 	struct input_dev *dev = evdev->handle.dev;
 	struct input_absinfo abs;
-	void __user *p = (void __user *)arg;
-	int __user *ip = (int __user *)arg;
+	int __user *ip = (int __user *)p;
 	int i, t, u, v;
 
-	if (!evdev->exist) return -ENODEV;
+	if (!evdev->exist)
+		return -ENODEV;
 
 	switch (cmd) {
 
@@ -308,26 +400,39 @@
 			return put_user(EV_VERSION, ip);
 
 		case EVIOCGID:
-			return copy_to_user(p, &dev->id, sizeof(struct input_id)) ? -EFAULT : 0;
+			if (copy_to_user(p, &dev->id, sizeof(struct input_id)))
+				return -EFAULT;
+
+			return 0;
 
 		case EVIOCGKEYCODE:
-			if (get_user(t, ip)) return -EFAULT;
-			if (t < 0 || t >= dev->keycodemax || !dev->keycodesize) return -EINVAL;
-			if (put_user(INPUT_KEYCODE(dev, t), ip + 1)) return -EFAULT;
+			if (get_user(t, ip))
+				return -EFAULT;
+			if (t < 0 || t >= dev->keycodemax || !dev->keycodesize)
+				return -EINVAL;
+			if (put_user(INPUT_KEYCODE(dev, t), ip + 1))
+				return -EFAULT;
 			return 0;
 
 		case EVIOCSKEYCODE:
-			if (get_user(t, ip)) return -EFAULT;
-			if (t < 0 || t >= dev->keycodemax || !dev->keycodesize) return -EINVAL;
-			if (get_user(v, ip + 1)) return -EFAULT;
-			if (v < 0 || v > KEY_MAX) return -EINVAL;
-			if (dev->keycodesize < sizeof(v) && (v >> (dev->keycodesize * 8))) return -EINVAL;
+			if (get_user(t, ip))
+				return -EFAULT;
+			if (t < 0 || t >= dev->keycodemax || !dev->keycodesize)
+				return -EINVAL;
+			if (get_user(v, ip + 1))
+				return -EFAULT;
+			if (v < 0 || v > KEY_MAX)
+				return -EINVAL;
+			if (dev->keycodesize < sizeof(v) && (v >> (dev->keycodesize * 8)))
+				return -EINVAL;
+
 			u = SET_INPUT_KEYCODE(dev, t, v);
 			clear_bit(u, dev->keybit);
 			set_bit(v, dev->keybit);
 			for (i = 0; i < dev->keycodemax; i++)
-				if (INPUT_KEYCODE(dev,i) == u)
+				if (INPUT_KEYCODE(dev, i) == u)
 					set_bit(u, dev->keybit);
+
 			return 0;
 
 		case EVIOCSFF:
@@ -338,17 +443,17 @@
 				if (copy_from_user(&effect, p, sizeof(effect)))
 					return -EFAULT;
 				err = dev->upload_effect(dev, &effect);
-				if (put_user(effect.id, &(((struct ff_effect __user *)arg)->id)))
+				if (put_user(effect.id, &(((struct ff_effect __user *)p)->id)))
 					return -EFAULT;
 				return err;
-			}
-			else return -ENOSYS;
+			} else
+				return -ENOSYS;
 
 		case EVIOCRMFF:
-			if (dev->erase_effect) {
-				return dev->erase_effect(dev, (int)arg);
-			}
-			else return -ENOSYS;
+			if (!dev->erase_effect)
+				return -ENOSYS;
+
+			return dev->erase_effect(dev, (int)(unsigned long) p);
 
 		case EVIOCGEFFECTS:
 			if (put_user(dev->ff_effects_max, ip))
@@ -356,7 +461,7 @@
 			return 0;
 
 		case EVIOCGRAB:
-			if (arg) {
+			if (p) {
 				if (evdev->grab)
 					return -EBUSY;
 				if (input_grab_device(&evdev->handle))
@@ -395,62 +500,33 @@
 						case EV_SW:  bits = dev->swbit;  len = SW_MAX;  break;
 						default: return -EINVAL;
 					}
-					len = NBITS(len) * sizeof(long);
-					if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
-					return copy_to_user(p, bits, len) ? -EFAULT : len;
+					return bits_to_user(bits, len, _IOC_SIZE(cmd), p, compat_mode);
 				}
 
-				if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0))) {
-					int len;
-					len = NBITS(KEY_MAX) * sizeof(long);
-					if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
-					return copy_to_user(p, dev->key, len) ? -EFAULT : len;
-				}
+				if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0)))
+					return bits_to_user(dev->key, KEY_MAX, _IOC_SIZE(cmd),
+							    p, compat_mode);
 
-				if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0))) {
-					int len;
-					len = NBITS(LED_MAX) * sizeof(long);
-					if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
-					return copy_to_user(p, dev->led, len) ? -EFAULT : len;
-				}
+				if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0)))
+					return bits_to_user(dev->led, LED_MAX, _IOC_SIZE(cmd),
+							    p, compat_mode);
 
-				if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0))) {
-					int len;
-					len = NBITS(SND_MAX) * sizeof(long);
-					if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
-					return copy_to_user(p, dev->snd, len) ? -EFAULT : len;
-				}
+				if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0)))
+					return bits_to_user(dev->snd, SND_MAX, _IOC_SIZE(cmd),
+							    p, compat_mode);
 
-				if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSW(0))) {
-					int len;
-					len = NBITS(SW_MAX) * sizeof(long);
-					if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
-					return copy_to_user(p, dev->sw, len) ? -EFAULT : len;
-				}
+				if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSW(0)))
+					return bits_to_user(dev->sw, SW_MAX, _IOC_SIZE(cmd),
+							    p, compat_mode);
 
-				if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) {
-					int len;
-					if (!dev->name) return -ENOENT;
-					len = strlen(dev->name) + 1;
-					if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
-					return copy_to_user(p, dev->name, len) ? -EFAULT : len;
-				}
+				if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0)))
+					return str_to_user(dev->name, _IOC_SIZE(cmd), p);
 
-				if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0))) {
-					int len;
-					if (!dev->phys) return -ENOENT;
-					len = strlen(dev->phys) + 1;
-					if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
-					return copy_to_user(p, dev->phys, len) ? -EFAULT : len;
-				}
+				if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0)))
+					return str_to_user(dev->phys, _IOC_SIZE(cmd), p);
 
-				if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0))) {
-					int len;
-					if (!dev->uniq) return -ENOENT;
-					len = strlen(dev->uniq) + 1;
-					if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
-					return copy_to_user(p, dev->uniq, len) ? -EFAULT : len;
-				}
+				if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0)))
+					return str_to_user(dev->uniq, _IOC_SIZE(cmd), p);
 
 				if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) {
 
@@ -492,158 +568,15 @@
 	return -EINVAL;
 }
 
+static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	return evdev_ioctl_handler(file, cmd, (void __user *)arg, 0);
+}
+
 #ifdef CONFIG_COMPAT
-
-#define BITS_PER_LONG_COMPAT (sizeof(compat_long_t) * 8)
-#define NBITS_COMPAT(x) ((((x)-1)/BITS_PER_LONG_COMPAT)+1)
-#define OFF_COMPAT(x)  ((x)%BITS_PER_LONG_COMPAT)
-#define BIT_COMPAT(x)  (1UL<<OFF_COMPAT(x))
-#define LONG_COMPAT(x) ((x)/BITS_PER_LONG_COMPAT)
-#define test_bit_compat(bit, array) ((array[LONG_COMPAT(bit)] >> OFF_COMPAT(bit)) & 1)
-
-#ifdef __BIG_ENDIAN
-#define bit_to_user(bit, max) \
-do { \
-	int i; \
-	int len = NBITS_COMPAT((max)) * sizeof(compat_long_t); \
-	if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); \
-	for (i = 0; i < len / sizeof(compat_long_t); i++) \
-		if (copy_to_user((compat_long_t __user *) p + i, \
-				 (compat_long_t*) (bit) + i + 1 - ((i % 2) << 1), \
-				 sizeof(compat_long_t))) \
-			return -EFAULT; \
-	return len; \
-} while (0)
-#else
-#define bit_to_user(bit, max) \
-do { \
-	int len = NBITS_COMPAT((max)) * sizeof(compat_long_t); \
-	if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); \
-	return copy_to_user(p, (bit), len) ? -EFAULT : len; \
-} while (0)
-#endif
-
 static long evdev_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
 {
-	struct evdev_list *list = file->private_data;
-	struct evdev *evdev = list->evdev;
-	struct input_dev *dev = evdev->handle.dev;
-	struct input_absinfo abs;
-	void __user *p = compat_ptr(arg);
-
-	if (!evdev->exist) return -ENODEV;
-
-	switch (cmd) {
-
-		case EVIOCGVERSION:
-		case EVIOCGID:
-		case EVIOCGKEYCODE:
-		case EVIOCSKEYCODE:
-		case EVIOCSFF:
-		case EVIOCRMFF:
-		case EVIOCGEFFECTS:
-		case EVIOCGRAB:
-			return evdev_ioctl(file, cmd, (unsigned long) p);
-
-		default:
-
-			if (_IOC_TYPE(cmd) != 'E')
-				return -EINVAL;
-
-			if (_IOC_DIR(cmd) == _IOC_READ) {
-
-				if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0,0))) {
-					long *bits;
-					int max;
-
-					switch (_IOC_NR(cmd) & EV_MAX) {
-						case      0: bits = dev->evbit;  max = EV_MAX;  break;
-						case EV_KEY: bits = dev->keybit; max = KEY_MAX; break;
-						case EV_REL: bits = dev->relbit; max = REL_MAX; break;
-						case EV_ABS: bits = dev->absbit; max = ABS_MAX; break;
-						case EV_MSC: bits = dev->mscbit; max = MSC_MAX; break;
-						case EV_LED: bits = dev->ledbit; max = LED_MAX; break;
-						case EV_SND: bits = dev->sndbit; max = SND_MAX; break;
-						case EV_FF:  bits = dev->ffbit;  max = FF_MAX;  break;
-						case EV_SW:  bits = dev->swbit;  max = SW_MAX;  break;
-						default: return -EINVAL;
-					}
-					bit_to_user(bits, max);
-				}
-
-				if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0)))
-					bit_to_user(dev->key, KEY_MAX);
-
-				if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0)))
-					bit_to_user(dev->led, LED_MAX);
-
-				if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0)))
-					bit_to_user(dev->snd, SND_MAX);
-
-				if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSW(0)))
-					bit_to_user(dev->sw, SW_MAX);
-
-				if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) {
-					int len;
-					if (!dev->name) return -ENOENT;
-					len = strlen(dev->name) + 1;
-					if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
-					return copy_to_user(p, dev->name, len) ? -EFAULT : len;
-				}
-
-				if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0))) {
-					int len;
-					if (!dev->phys) return -ENOENT;
-					len = strlen(dev->phys) + 1;
-					if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
-					return copy_to_user(p, dev->phys, len) ? -EFAULT : len;
-				}
-
-				if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0))) {
-					int len;
-					if (!dev->uniq) return -ENOENT;
-					len = strlen(dev->uniq) + 1;
-					if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
-					return copy_to_user(p, dev->uniq, len) ? -EFAULT : len;
-				}
-
-				if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) {
-
-					int t = _IOC_NR(cmd) & ABS_MAX;
-
-					abs.value = dev->abs[t];
-					abs.minimum = dev->absmin[t];
-					abs.maximum = dev->absmax[t];
-					abs.fuzz = dev->absfuzz[t];
-					abs.flat = dev->absflat[t];
-
-					if (copy_to_user(p, &abs, sizeof(struct input_absinfo)))
-						return -EFAULT;
-
-					return 0;
-				}
-			}
-
-			if (_IOC_DIR(cmd) == _IOC_WRITE) {
-
-				if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) {
-
-					int t = _IOC_NR(cmd) & ABS_MAX;
-
-					if (copy_from_user(&abs, p, sizeof(struct input_absinfo)))
-						return -EFAULT;
-
-					dev->abs[t] = abs.value;
-					dev->absmin[t] = abs.minimum;
-					dev->absmax[t] = abs.maximum;
-					dev->absfuzz[t] = abs.fuzz;
-					dev->absflat[t] = abs.flat;
-
-					return 0;
-				}
-			}
-	}
-	return -EINVAL;
+	return evdev_ioctl_handler(file, cmd, compat_ptr(arg), 1);
 }
 #endif
 
diff --git a/drivers/input/gameport/Kconfig b/drivers/input/gameport/Kconfig
index 7524bd7..d279454 100644
--- a/drivers/input/gameport/Kconfig
+++ b/drivers/input/gameport/Kconfig
@@ -52,5 +52,12 @@
 config GAMEPORT_FM801
 	tristate "ForteMedia FM801 gameport support"
 	depends on PCI
+	help
+	  Say Y here if you have ForteMedia FM801 PCI audio controller
+	  (Abit AU10, Genius Sound Maker, HP Workstation zx2000,
+	  and others), and want to use its gameport.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called fm801-gp.
 
 endif
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index a0256f8..ffacf6e 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -321,7 +321,7 @@
 	switch (code) {
 		case ATKBD_RET_BAT:
 			atkbd->enabled = 0;
-			serio_rescan(atkbd->ps2dev.serio);
+			serio_reconnect(atkbd->ps2dev.serio);
 			goto out;
 		case ATKBD_RET_EMUL0:
 			atkbd->emul = 1;
diff --git a/drivers/input/misc/m68kspkr.c b/drivers/input/misc/m68kspkr.c
index 04489ad..8d6c383 100644
--- a/drivers/input/misc/m68kspkr.c
+++ b/drivers/input/misc/m68kspkr.c
@@ -17,6 +17,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/input.h>
+#include <linux/platform_device.h>
 #include <asm/machdep.h>
 #include <asm/io.h>
 
@@ -24,7 +25,7 @@
 MODULE_DESCRIPTION("m68k beeper driver");
 MODULE_LICENSE("GPL");
 
-static struct input_dev *m68kspkr_dev;
+static struct platform_device *m68kspkr_platform_device;
 
 static int m68kspkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
 {
@@ -47,36 +48,103 @@
 	return 0;
 }
 
-static int __init m68kspkr_init(void)
+static int __devinit m68kspkr_probe(struct platform_device *dev)
 {
-        if (!mach_beep) {
-		printk(KERN_INFO "m68kspkr: no lowlevel beep support\n");
-		return -ENODEV;
-        }
+	struct input_dev *input_dev;
+	int err;
 
-	m68kspkr_dev = input_allocate_device();
-	if (!m68kspkr_dev)
+	input_dev = input_allocate_device();
+	if (!input_dev)
 		return -ENOMEM;
 
-	m68kspkr_dev->name = "m68k beeper";
-	m68kspkr_dev->phys = "m68k/generic";
-	m68kspkr_dev->id.bustype = BUS_HOST;
-	m68kspkr_dev->id.vendor = 0x001f;
-	m68kspkr_dev->id.product = 0x0001;
-	m68kspkr_dev->id.version = 0x0100;
+	input_dev->name = "m68k beeper";
+	input_dev->phys = "m68k/generic";
+	input_dev->id.bustype = BUS_HOST;
+	input_dev->id.vendor  = 0x001f;
+	input_dev->id.product = 0x0001;
+	input_dev->id.version = 0x0100;
+	input_dev->cdev.dev = &dev->dev;
 
-	m68kspkr_dev->evbit[0] = BIT(EV_SND);
-	m68kspkr_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
-	m68kspkr_dev->event = m68kspkr_event;
+	input_dev->evbit[0] = BIT(EV_SND);
+	input_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
+	input_dev->event = m68kspkr_event;
 
-	input_register_device(m68kspkr_dev);
+	err = input_register_device(input_dev);
+	if (err) {
+		input_free_device(input_dev);
+		return err;
+	}
+
+	platform_set_drvdata(dev, input_dev);
 
 	return 0;
 }
 
+static int __devexit m68kspkr_remove(struct platform_device *dev)
+{
+	struct input_dev *input_dev = platform_get_drvdata(dev);
+
+	input_unregister_device(input_dev);
+	platform_set_drvdata(dev, NULL);
+	/* turn off the speaker */
+	m68kspkr_event(NULL, EV_SND, SND_BELL, 0);
+
+	return 0;
+}
+
+static void m68kspkr_shutdown(struct platform_device *dev)
+{
+	/* turn off the speaker */
+	m68kspkr_event(NULL, EV_SND, SND_BELL, 0);
+}
+
+static struct platform_driver m68kspkr_platform_driver = {
+	.driver		= {
+		.name	= "m68kspkr",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= m68kspkr_probe,
+	.remove		= __devexit_p(m68kspkr_remove),
+	.shutdown	= m68kspkr_shutdown,
+};
+
+static int __init m68kspkr_init(void)
+{
+	int err;
+
+	if (!mach_beep) {
+		printk(KERN_INFO "m68kspkr: no lowlevel beep support\n");
+		return -ENODEV;
+        }
+
+	err = platform_driver_register(&m68kspkr_platform_driver);
+	if (err)
+		return err;
+
+	m68kspkr_platform_device = platform_device_alloc("m68kspkr", -1);
+	if (!m68kspkr_platform_device) {
+		err = -ENOMEM;
+		goto err_unregister_driver;
+	}
+
+	err = platform_device_add(m68kspkr_platform_device);
+	if (err)
+		goto err_free_device;
+
+	return 0;
+
+ err_free_device:
+	platform_device_put(m68kspkr_platform_device);
+ err_unregister_driver:
+	platform_driver_unregister(&m68kspkr_platform_driver);
+
+	return err;
+}
+
 static void __exit m68kspkr_exit(void)
 {
-        input_unregister_device(m68kspkr_dev);
+	platform_device_unregister(m68kspkr_platform_device);
+	platform_driver_unregister(&m68kspkr_platform_driver);
 }
 
 module_init(m68kspkr_init);
diff --git a/drivers/input/misc/pcspkr.c b/drivers/input/misc/pcspkr.c
index 68ac97f..1ef477f 100644
--- a/drivers/input/misc/pcspkr.c
+++ b/drivers/input/misc/pcspkr.c
@@ -16,6 +16,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/input.h>
+#include <linux/platform_device.h>
 #include <asm/8253pit.h>
 #include <asm/io.h>
 
@@ -23,8 +24,7 @@
 MODULE_DESCRIPTION("PC Speaker beeper driver");
 MODULE_LICENSE("GPL");
 
-static struct input_dev *pcspkr_dev;
-
+static struct platform_device *pcspkr_platform_device;
 static DEFINE_SPINLOCK(i8253_beep_lock);
 
 static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
@@ -64,8 +64,11 @@
 	return 0;
 }
 
-static int __init pcspkr_init(void)
+static int __devinit pcspkr_probe(struct platform_device *dev)
 {
+	struct input_dev *pcspkr_dev;
+	int err;
+
 	pcspkr_dev = input_allocate_device();
 	if (!pcspkr_dev)
 		return -ENOMEM;
@@ -76,21 +79,92 @@
 	pcspkr_dev->id.vendor = 0x001f;
 	pcspkr_dev->id.product = 0x0001;
 	pcspkr_dev->id.version = 0x0100;
+	pcspkr_dev->cdev.dev = &dev->dev;
 
 	pcspkr_dev->evbit[0] = BIT(EV_SND);
 	pcspkr_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
 	pcspkr_dev->event = pcspkr_event;
 
-	input_register_device(pcspkr_dev);
+	err = input_register_device(pcspkr_dev);
+	if (err) {
+		input_free_device(pcspkr_dev);
+		return err;
+	}
+
+	platform_set_drvdata(dev, pcspkr_dev);
 
 	return 0;
 }
 
-static void __exit pcspkr_exit(void)
+static int __devexit pcspkr_remove(struct platform_device *dev)
 {
-        input_unregister_device(pcspkr_dev);
+	struct input_dev *pcspkr_dev = platform_get_drvdata(dev);
+
+	input_unregister_device(pcspkr_dev);
+	platform_set_drvdata(dev, NULL);
 	/* turn off the speaker */
 	pcspkr_event(NULL, EV_SND, SND_BELL, 0);
+
+	return 0;
+}
+
+static int pcspkr_suspend(struct platform_device *dev, pm_message_t state)
+{
+	pcspkr_event(NULL, EV_SND, SND_BELL, 0);
+
+	return 0;
+}
+
+static void pcspkr_shutdown(struct platform_device *dev)
+{
+	/* turn off the speaker */
+	pcspkr_event(NULL, EV_SND, SND_BELL, 0);
+}
+
+static struct platform_driver pcspkr_platform_driver = {
+	.driver		= {
+		.name	= "pcspkr",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= pcspkr_probe,
+	.remove		= __devexit_p(pcspkr_remove),
+	.suspend	= pcspkr_suspend,
+	.shutdown	= pcspkr_shutdown,
+};
+
+
+static int __init pcspkr_init(void)
+{
+	int err;
+
+	err = platform_driver_register(&pcspkr_platform_driver);
+	if (err)
+		return err;
+
+	pcspkr_platform_device = platform_device_alloc("pcspkr", -1);
+	if (!pcspkr_platform_device) {
+		err = -ENOMEM;
+		goto err_unregister_driver;
+	}
+
+	err = platform_device_add(pcspkr_platform_device);
+	if (err)
+		goto err_free_device;
+
+	return 0;
+
+ err_free_device:
+	platform_device_put(pcspkr_platform_device);
+ err_unregister_driver:
+	platform_driver_unregister(&pcspkr_platform_driver);
+
+	return err;
+}
+
+static void __exit pcspkr_exit(void)
+{
+	platform_device_unregister(pcspkr_platform_device);
+	platform_driver_unregister(&pcspkr_platform_driver);
 }
 
 module_init(pcspkr_init);
diff --git a/drivers/input/misc/sparcspkr.c b/drivers/input/misc/sparcspkr.c
index 29d97b1..f0fd2c4 100644
--- a/drivers/input/misc/sparcspkr.c
+++ b/drivers/input/misc/sparcspkr.c
@@ -9,6 +9,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/input.h>
+#include <linux/platform_device.h>
 
 #include <asm/io.h>
 #include <asm/ebus.h>
@@ -20,22 +21,10 @@
 MODULE_DESCRIPTION("Sparc Speaker beeper driver");
 MODULE_LICENSE("GPL");
 
+const char *beep_name;
 static unsigned long beep_iobase;
-static struct input_dev *sparcspkr_dev;
-
-DEFINE_SPINLOCK(beep_lock);
-
-static void __init init_sparcspkr_struct(void)
-{
-	sparcspkr_dev->evbit[0] = BIT(EV_SND);
-	sparcspkr_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
-
-	sparcspkr_dev->phys = "sparc/input0";
-	sparcspkr_dev->id.bustype = BUS_ISA;
-	sparcspkr_dev->id.vendor = 0x001f;
-	sparcspkr_dev->id.product = 0x0001;
-	sparcspkr_dev->id.version = 0x0100;
-}
+static int (*beep_event)(struct input_dev *dev, unsigned int type, unsigned int code, int value);
+static DEFINE_SPINLOCK(beep_lock);
 
 static int ebus_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
 {
@@ -59,39 +48,16 @@
 	/* EBUS speaker only has on/off state, the frequency does not
 	 * appear to be programmable.
 	 */
-	if (count) {
-		if (beep_iobase & 0x2UL)
-			outb(1, beep_iobase);
-		else
-			outl(1, beep_iobase);
-	} else {
-		if (beep_iobase & 0x2UL)
-			outb(0, beep_iobase);
-		else
-			outl(0, beep_iobase);
-	}
+	if (beep_iobase & 0x2UL)
+		outb(!!count, beep_iobase);
+	else
+		outl(!!count, beep_iobase);
 
 	spin_unlock_irqrestore(&beep_lock, flags);
 
 	return 0;
 }
 
-static int __init init_ebus_beep(struct linux_ebus_device *edev)
-{
-	beep_iobase = edev->resource[0].start;
-
-	sparcspkr_dev = input_allocate_device();
-	if (!sparcspkr_dev)
-		return -ENOMEM;
-
-	sparcspkr_dev->name = "Sparc EBUS Speaker";
-	sparcspkr_dev->event = ebus_spkr_event;
-
-	input_register_device(sparcspkr_dev);
-
-	return 0;
-}
-
 #ifdef CONFIG_SPARC64
 static int isa_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
 {
@@ -129,30 +95,103 @@
 
 	return 0;
 }
+#endif
 
-static int __init init_isa_beep(struct sparc_isa_device *isa_dev)
+static int __devinit sparcspkr_probe(struct platform_device *dev)
 {
-	beep_iobase = isa_dev->resource.start;
+	struct input_dev *input_dev;
+	int error;
 
-	sparcspkr_dev = input_allocate_device();
-	if (!sparcspkr_dev)
+	input_dev = input_allocate_device();
+	if (!input_dev)
 		return -ENOMEM;
 
-	init_sparcspkr_struct();
+	input_dev->name = beep_name;
+	input_dev->phys = "sparc/input0";
+	input_dev->id.bustype = BUS_ISA;
+	input_dev->id.vendor = 0x001f;
+	input_dev->id.product = 0x0001;
+	input_dev->id.version = 0x0100;
+	input_dev->cdev.dev = &dev->dev;
 
-	sparcspkr_dev->name = "Sparc ISA Speaker";
-	sparcspkr_dev->event = isa_spkr_event;
+	input_dev->evbit[0] = BIT(EV_SND);
+	input_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
 
-	input_register_device(sparcspkr_dev);
+	input_dev->event = beep_event;
+
+	error = input_register_device(input_dev);
+	if (error) {
+		input_free_device(input_dev);
+		return error;
+	}
+
+	platform_set_drvdata(dev, input_dev);
 
 	return 0;
 }
-#endif
+
+static int __devexit sparcspkr_remove(struct platform_device *dev)
+{
+	struct input_dev *input_dev = platform_get_drvdata(dev);
+
+	input_unregister_device(input_dev);
+	platform_set_drvdata(dev, NULL);
+	/* turn off the speaker */
+	beep_event(NULL, EV_SND, SND_BELL, 0);
+
+	return 0;
+}
+
+static void sparcspkr_shutdown(struct platform_device *dev)
+{
+	/* turn off the speaker */
+	beep_event(NULL, EV_SND, SND_BELL, 0);
+}
+
+static struct platform_driver sparcspkr_platform_driver = {
+	.driver		= {
+		.name	= "sparcspkr",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= sparcspkr_probe,
+	.remove		= __devexit_p(sparcspkr_remove),
+	.shutdown	= sparcspkr_shutdown,
+};
+
+static struct platform_device *sparcspkr_platform_device;
+
+static int __init sparcspkr_drv_init(void)
+{
+	int error;
+
+	error = platform_driver_register(&sparcspkr_platform_driver);
+	if (error)
+		return error;
+
+	sparcspkr_platform_device = platform_device_alloc("sparcspkr", -1);
+	if (!sparcspkr_platform_device) {
+		error = -ENOMEM;
+		goto err_unregister_driver;
+	}
+
+	error = platform_device_add(sparcspkr_platform_device);
+	if (error)
+		goto err_free_device;
+
+	return 0;
+
+ err_free_device:
+	platform_device_put(sparcspkr_platform_device);
+ err_unregister_driver:
+	platform_driver_unregister(&sparcspkr_platform_driver);
+
+	return error;
+}
 
 static int __init sparcspkr_init(void)
 {
 	struct linux_ebus *ebus;
-	struct linux_ebus_device *edev = NULL;
+	struct linux_ebus_device *edev;
 #ifdef CONFIG_SPARC64
 	struct sparc_isa_bridge *isa_br;
 	struct sparc_isa_device *isa_dev;
@@ -160,8 +199,12 @@
 
 	for_each_ebus(ebus) {
 		for_each_ebusdev(edev, ebus) {
-			if (!strcmp(edev->prom_name, "beep"))
-				return init_ebus_beep(edev);
+			if (!strcmp(edev->prom_name, "beep")) {
+				beep_name = "Sparc EBUS Speaker";
+				beep_event = ebus_spkr_event;
+				beep_iobase = edev->resource[0].start;
+				return sparcspkr_drv_init();
+			}
 		}
 	}
 #ifdef CONFIG_SPARC64
@@ -170,8 +213,12 @@
 			/* A hack, the beep device's base lives in
 			 * the DMA isa node.
 			 */
-			if (!strcmp(isa_dev->prom_name, "dma"))
-				return init_isa_beep(isa_dev);
+			if (!strcmp(isa_dev->prom_name, "dma")) {
+				beep_name = "Sparc ISA Speaker";
+				beep_event = isa_spkr_event,
+				beep_iobase = isa_dev->resource.start;
+				return sparcspkr_drv_init();
+			}
 		}
 	}
 #endif
@@ -181,7 +228,8 @@
 
 static void __exit sparcspkr_exit(void)
 {
-	input_unregister_device(sparcspkr_dev);
+	platform_device_unregister(sparcspkr_platform_device);
+	platform_driver_unregister(&sparcspkr_platform_driver);
 }
 
 module_init(sparcspkr_init);
diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c
index bac3085..a05b855 100644
--- a/drivers/input/misc/wistron_btns.c
+++ b/drivers/input/misc/wistron_btns.c
@@ -174,7 +174,7 @@
 	return regs.eax;
 }
 
-static void __init bios_attach(void)
+static void __devinit bios_attach(void)
 {
 	struct regs regs;
 
@@ -194,7 +194,7 @@
 	call_bios(&regs);
 }
 
-static u8 __init bios_get_cmos_address(void)
+static u8 __devinit bios_get_cmos_address(void)
 {
 	struct regs regs;
 
@@ -206,7 +206,7 @@
 	return regs.ecx;
 }
 
-static u16 __init bios_get_default_setting(u8 subsys)
+static u16 __devinit bios_get_default_setting(u8 subsys)
 {
 	struct regs regs;
 
@@ -296,6 +296,16 @@
 	{ KE_END, 0 }
 };
 
+static struct key_entry keymap_acer_travelmate_240[] = {
+	{ KE_KEY, 0x31, KEY_MAIL },
+	{ KE_KEY, 0x36, KEY_WWW },
+	{ KE_KEY, 0x11, KEY_PROG1 },
+	{ KE_KEY, 0x12, KEY_PROG2 },
+	{ KE_BLUETOOTH, 0x44, 0 },
+	{ KE_WIFI, 0x30, 0 },
+	{ KE_END, 0 }
+};
+
 /*
  * If your machine is not here (which is currently rather likely), please send
  * a list of buttons and their key codes (reported when loading this module
@@ -320,6 +330,15 @@
 		},
 		.driver_data = keymap_acer_aspire_1500
 	},
+	{
+		.callback = dmi_matched,
+		.ident = "Acer TravelMate 240",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 240"),
+		},
+		.driver_data = keymap_acer_travelmate_240
+	},
 	{ NULL, }
 };
 
@@ -348,7 +367,7 @@
 
 static struct input_dev *input_dev;
 
-static int __init setup_input_dev(void)
+static int __devinit setup_input_dev(void)
 {
 	const struct key_entry *key;
 	int error;
@@ -447,6 +466,52 @@
 	mod_timer(&poll_timer, jiffies + HZ / POLL_FREQUENCY);
 }
 
+static int __devinit wistron_probe(struct platform_device *dev)
+{
+	int err = setup_input_dev();
+	if (err)
+		return err;
+
+	bios_attach();
+	cmos_address = bios_get_cmos_address();
+
+	if (have_wifi) {
+		u16 wifi = bios_get_default_setting(WIFI);
+		if (wifi & 1)
+			wifi_enabled = (wifi & 2) ? 1 : 0;
+		else
+			have_wifi = 0;
+
+		if (have_wifi)
+			bios_set_state(WIFI, wifi_enabled);
+	}
+
+	if (have_bluetooth) {
+		u16 bt = bios_get_default_setting(BLUETOOTH);
+		if (bt & 1)
+			bluetooth_enabled = (bt & 2) ? 1 : 0;
+		else
+			have_bluetooth = 0;
+
+		if (have_bluetooth)
+			bios_set_state(BLUETOOTH, bluetooth_enabled);
+	}
+
+	poll_bios(1); /* Flush stale event queue and arm timer */
+
+	return 0;
+}
+
+static int __devexit wistron_remove(struct platform_device *dev)
+{
+	del_timer_sync(&poll_timer);
+	input_unregister_device(input_dev);
+	bios_detach();
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
 static int wistron_suspend(struct platform_device *dev, pm_message_t state)
 {
 	del_timer_sync(&poll_timer);
@@ -472,13 +537,20 @@
 
 	return 0;
 }
+#else
+#define wistron_suspend		NULL
+#define wistron_resume		NULL
+#endif
 
 static struct platform_driver wistron_driver = {
-	.suspend	= wistron_suspend,
-	.resume		= wistron_resume,
 	.driver		= {
 		.name	= "wistron-bios",
+		.owner	= THIS_MODULE,
 	},
+	.probe		= wistron_probe,
+	.remove		= __devexit_p(wistron_remove),
+	.suspend	= wistron_suspend,
+	.resume		= wistron_resume,
 };
 
 static int __init wb_module_init(void)
@@ -493,55 +565,27 @@
 	if (err)
 		return err;
 
-	bios_attach();
-	cmos_address = bios_get_cmos_address();
-
 	err = platform_driver_register(&wistron_driver);
 	if (err)
-		goto err_detach_bios;
+		goto err_unmap_bios;
 
-	wistron_device = platform_device_register_simple("wistron-bios", -1, NULL, 0);
-	if (IS_ERR(wistron_device)) {
-		err = PTR_ERR(wistron_device);
+	wistron_device = platform_device_alloc("wistron-bios", -1);
+	if (!wistron_device) {
+		err = -ENOMEM;
 		goto err_unregister_driver;
 	}
 
-	if (have_wifi) {
-		u16 wifi = bios_get_default_setting(WIFI);
-		if (wifi & 1)
-			wifi_enabled = (wifi & 2) ? 1 : 0;
-		else
-			have_wifi = 0;
-
-		if (have_wifi)
-			bios_set_state(WIFI, wifi_enabled);
-	}
-
-	if (have_bluetooth) {
-		u16 bt = bios_get_default_setting(BLUETOOTH);
-		if (bt & 1)
-			bluetooth_enabled = (bt & 2) ? 1 : 0;
-		else
-			have_bluetooth = 0;
-
-		if (have_bluetooth)
-			bios_set_state(BLUETOOTH, bluetooth_enabled);
-	}
-
-	err = setup_input_dev();
+	err = platform_device_add(wistron_device);
 	if (err)
-		goto err_unregister_device;
-
-	poll_bios(1); /* Flush stale event queue and arm timer */
+		goto err_free_device;
 
 	return 0;
 
- err_unregister_device:
-	platform_device_unregister(wistron_device);
+ err_free_device:
+	platform_device_put(wistron_device);
  err_unregister_driver:
 	platform_driver_unregister(&wistron_driver);
- err_detach_bios:
-	bios_detach();
+ err_unmap_bios:
 	unmap_bios();
 
 	return err;
@@ -549,11 +593,8 @@
 
 static void __exit wb_module_exit(void)
 {
-	del_timer_sync(&poll_timer);
-	input_unregister_device(input_dev);
 	platform_device_unregister(wistron_device);
 	platform_driver_unregister(&wistron_driver);
-	bios_detach();
 	unmap_bios();
 }
 
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index 4f41ec3..2447433 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -40,6 +40,7 @@
 	{ { 0x33, 0x02, 0x0a },	0x88, 0xf8, ALPS_OLDPROTO },		/* UMAX-530T */
 	{ { 0x53, 0x02, 0x0a },	0xf8, 0xf8, 0 },
 	{ { 0x53, 0x02, 0x14 },	0xf8, 0xf8, 0 },
+	{ { 0x60, 0x03, 0xc8 }, 0xf8, 0xf8, 0 },			/* HP ze1115 */
 	{ { 0x63, 0x02, 0x0a },	0xf8, 0xf8, 0 },
 	{ { 0x63, 0x02, 0x14 },	0xf8, 0xf8, 0 },
 	{ { 0x63, 0x02, 0x28 },	0xf8, 0xf8, ALPS_FW_BK_2 },		/* Fujitsu Siemens S6010 */
diff --git a/drivers/input/mouse/lifebook.c b/drivers/input/mouse/lifebook.c
index 5599142..5ccc3ef 100644
--- a/drivers/input/mouse/lifebook.c
+++ b/drivers/input/mouse/lifebook.c
@@ -27,6 +27,13 @@
                        DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK B Series"),
                },
        },
+       {
+               .ident = "Lifebook B142",
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B142"),
+               },
+
+       },
        { }
 };
 
diff --git a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c
index 31a59f7..025a71d 100644
--- a/drivers/input/mouse/logips2pp.c
+++ b/drivers/input/mouse/logips2pp.c
@@ -226,7 +226,9 @@
 		{ 80,	PS2PP_KIND_WHEEL,	PS2PP_SIDE_BTN | PS2PP_WHEEL },
 		{ 81,	PS2PP_KIND_WHEEL,	PS2PP_WHEEL },
 		{ 83,	PS2PP_KIND_WHEEL,	PS2PP_WHEEL },
+		{ 85,	PS2PP_KIND_WHEEL,	PS2PP_WHEEL },
 		{ 86,	PS2PP_KIND_WHEEL,	PS2PP_WHEEL },
+		{ 87,	PS2PP_KIND_WHEEL,	PS2PP_WHEEL },
 		{ 88,	PS2PP_KIND_WHEEL,	PS2PP_WHEEL },
 		{ 96,	0,			0 },
 		{ 97,	PS2PP_KIND_TP3,		PS2PP_WHEEL | PS2PP_HWHEEL },
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
index 6ee9999..4d5ecc0 100644
--- a/drivers/input/mouse/psmouse-base.c
+++ b/drivers/input/mouse/psmouse-base.c
@@ -527,11 +527,15 @@
 	if (max_proto > PSMOUSE_IMEX && ps2pp_init(psmouse, set_properties) == 0)
 		return PSMOUSE_PS2PP;
 
+	if (max_proto > PSMOUSE_IMEX && trackpoint_detect(psmouse, set_properties) == 0)
+		return PSMOUSE_TRACKPOINT;
+
 /*
  * Reset to defaults in case the device got confused by extended
- * protocol probes.
+ * protocol probes. Note that we do full reset becuase some mice
+ * put themselves to sleep when see PSMOUSE_RESET_DIS.
  */
-	ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_RESET_DIS);
+	psmouse_reset(psmouse);
 
 	if (max_proto >= PSMOUSE_IMEX && im_explorer_detect(psmouse, set_properties) == 0)
 		return PSMOUSE_IMEX;
@@ -540,12 +544,6 @@
 		return PSMOUSE_IMPS;
 
 /*
- * Try to initialize the IBM TrackPoint
- */
-	if (max_proto > PSMOUSE_IMEX && trackpoint_detect(psmouse, set_properties) == 0)
-		return PSMOUSE_TRACKPOINT;
-
-/*
  * Okay, all failed, we have a standard mouse here. The number of the buttons
  * is still a question, though. We assume 3.
  */
@@ -559,7 +557,6 @@
  * extensions.
  */
 		psmouse_reset(psmouse);
-		ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_RESET_DIS);
 	}
 
 	return PSMOUSE_PS2;
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c
index 2d0af44..81fd7a9 100644
--- a/drivers/input/mousedev.c
+++ b/drivers/input/mousedev.c
@@ -40,15 +40,15 @@
 #endif
 
 static int xres = CONFIG_INPUT_MOUSEDEV_SCREEN_X;
-module_param(xres, uint, 0);
+module_param(xres, uint, 0644);
 MODULE_PARM_DESC(xres, "Horizontal screen resolution");
 
 static int yres = CONFIG_INPUT_MOUSEDEV_SCREEN_Y;
-module_param(yres, uint, 0);
+module_param(yres, uint, 0644);
 MODULE_PARM_DESC(yres, "Vertical screen resolution");
 
 static unsigned tap_time = 200;
-module_param(tap_time, uint, 0);
+module_param(tap_time, uint, 0644);
 MODULE_PARM_DESC(tap_time, "Tap time for touchpads in absolute mode (msecs)");
 
 struct mousedev_hw_data {
@@ -155,7 +155,7 @@
 	switch (code) {
 		case ABS_X:
 			size = dev->absmax[ABS_X] - dev->absmin[ABS_X];
-			if (size == 0) size = xres;
+			if (size == 0) size = xres ? : 1;
 			if (value > dev->absmax[ABS_X]) value = dev->absmax[ABS_X];
 			if (value < dev->absmin[ABS_X]) value = dev->absmin[ABS_X];
 			mousedev->packet.x = ((value - dev->absmin[ABS_X]) * xres) / size;
@@ -164,7 +164,7 @@
 
 		case ABS_Y:
 			size = dev->absmax[ABS_Y] - dev->absmin[ABS_Y];
-			if (size == 0) size = yres;
+			if (size == 0) size = yres ? : 1;
 			if (value > dev->absmax[ABS_Y]) value = dev->absmax[ABS_Y];
 			if (value < dev->absmin[ABS_Y]) value = dev->absmin[ABS_Y];
 			mousedev->packet.y = yres - ((value - dev->absmin[ABS_Y]) * yres) / size;
diff --git a/drivers/input/serio/ct82c710.c b/drivers/input/serio/ct82c710.c
index 4da6c86..096b6a0 100644
--- a/drivers/input/serio/ct82c710.c
+++ b/drivers/input/serio/ct82c710.c
@@ -154,7 +154,7 @@
  * See if we can find a 82C710 device. Read mouse address.
  */
 
-static int __init ct82c710_probe(void)
+static int __init ct82c710_detect(void)
 {
 	outb_p(0x55, 0x2fa);				/* Any value except 9, ff or 36 */
 	outb_p(0xaa, 0x3fa);				/* Inverse of 55 */
@@ -163,7 +163,7 @@
 	outb_p(0x1b, 0x2fa);				/* Inverse of e4 */
 	outb_p(0x0f, 0x390);				/* Write index */
 	if (inb_p(0x391) != 0xe4)			/* Config address found? */
-		return -1;				/* No: no 82C710 here */
+		return -ENODEV;				/* No: no 82C710 here */
 
 	outb_p(0x0d, 0x390);				/* Write index */
 	ct82c710_iores.start = inb_p(0x391) << 2;	/* Get mouse I/O address */
@@ -175,51 +175,88 @@
 	return 0;
 }
 
-static struct serio * __init ct82c710_allocate_port(void)
+static int __devinit ct82c710_probe(struct platform_device *dev)
 {
-	struct serio *serio;
+	ct82c710_port = kzalloc(sizeof(struct serio), GFP_KERNEL);
+	if (!ct82c710_port)
+		return -ENOMEM;
 
-	serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
-	if (serio) {
-		memset(serio, 0, sizeof(struct serio));
-		serio->id.type = SERIO_8042;
-		serio->open = ct82c710_open;
-		serio->close = ct82c710_close;
-		serio->write = ct82c710_write;
-		serio->dev.parent = &ct82c710_device->dev;
-		strlcpy(serio->name, "C&T 82c710 mouse port", sizeof(serio->name));
-		snprintf(serio->phys, sizeof(serio->phys), "isa%04lx/serio0", CT82C710_DATA);
-	}
+	ct82c710_port->id.type = SERIO_8042;
+	ct82c710_port->dev.parent = &dev->dev;
+	ct82c710_port->open = ct82c710_open;
+	ct82c710_port->close = ct82c710_close;
+	ct82c710_port->write = ct82c710_write;
+	strlcpy(ct82c710_port->name, "C&T 82c710 mouse port",
+		sizeof(ct82c710_port->name));
+	snprintf(ct82c710_port->phys, sizeof(ct82c710_port->phys),
+		 "isa%04lx/serio0", CT82C710_DATA);
 
-	return serio;
+	serio_register_port(ct82c710_port);
+
+	return 0;
 }
 
+static int __devexit ct82c710_remove(struct platform_device *dev)
+{
+	serio_unregister_port(ct82c710_port);
+
+	return 0;
+}
+
+static struct platform_driver ct82c710_driver = {
+	.driver		= {
+		.name	= "ct82c710",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= ct82c710_probe,
+	.remove		= __devexit_p(ct82c710_remove),
+};
+
+
 static int __init ct82c710_init(void)
 {
-	if (ct82c710_probe())
-		return -ENODEV;
+	int error;
 
-	ct82c710_device = platform_device_register_simple("ct82c710", -1, &ct82c710_iores, 1);
-	if (IS_ERR(ct82c710_device))
-		return PTR_ERR(ct82c710_device);
+	error = ct82c710_detect();
+	if (error)
+		return error;
 
-	if (!(ct82c710_port = ct82c710_allocate_port())) {
-		platform_device_unregister(ct82c710_device);
-		return -ENOMEM;
+	error = platform_driver_register(&ct82c710_driver);
+	if (error)
+		return error;
+
+	ct82c710_device = platform_device_alloc("ct82c710", -1);
+	if (!ct82c710_device) {
+		error = -ENOMEM;
+		goto err_unregister_driver;
 	}
 
+	error = platform_device_add_resources(ct82c710_device, &ct82c710_iores, 1);
+	if (error)
+		goto err_free_device;
+
+	error = platform_device_add(ct82c710_device);
+	if (error)
+		goto err_free_device;
+
 	serio_register_port(ct82c710_port);
 
 	printk(KERN_INFO "serio: C&T 82c710 mouse port at %#lx irq %d\n",
 		CT82C710_DATA, CT82C710_IRQ);
 
 	return 0;
+
+ err_free_device:
+	platform_device_put(ct82c710_device);
+ err_unregister_driver:
+	platform_driver_unregister(&ct82c710_driver);
+	return error;
 }
 
 static void __exit ct82c710_exit(void)
 {
-	serio_unregister_port(ct82c710_port);
 	platform_device_unregister(ct82c710_device);
+	platform_driver_unregister(&ct82c710_driver);
 }
 
 module_init(ct82c710_init);
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h
index 273bb3b..2d2f9fb 100644
--- a/drivers/input/serio/i8042-x86ia64io.h
+++ b/drivers/input/serio/i8042-x86ia64io.h
@@ -84,6 +84,14 @@
 			DMI_MATCH(DMI_PRODUCT_VERSION, "DL760"),
 		},
 	},
+	{
+		.ident = "OQO Model 01",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "OQO"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "ZEPTO"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "00"),
+		},
+	},
 	{ }
 };
 
@@ -158,6 +166,13 @@
 			DMI_MATCH(DMI_PRODUCT_NAME, "Sentia"),
 		},
 	},
+	{
+		.ident = "Sharp Actius MM20",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "SHARP"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "PC-MM20 Series"),
+		},
+	},
 	{ }
 };
 
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
index ac86c1d..a7d91d5 100644
--- a/drivers/input/serio/i8042.c
+++ b/drivers/input/serio/i8042.c
@@ -572,7 +572,7 @@
  * LCS/Telegraphics.
  */
 
-static int __init i8042_check_mux(void)
+static int __devinit i8042_check_mux(void)
 {
 	unsigned char mux_version;
 
@@ -600,7 +600,7 @@
  * the presence of an AUX interface.
  */
 
-static int __init i8042_check_aux(void)
+static int __devinit i8042_check_aux(void)
 {
 	unsigned char param;
 	static int i8042_check_aux_cookie;
@@ -678,7 +678,7 @@
  * registers it, and reports to the user.
  */
 
-static int __init i8042_port_register(struct i8042_port *port)
+static int __devinit i8042_port_register(struct i8042_port *port)
 {
 	i8042_ctr &= ~port->disable;
 
@@ -956,7 +956,6 @@
 	panic_blink = i8042_panic_blink;
 
 	return 0;
-
 }
 
 /*
@@ -969,16 +968,7 @@
 	i8042_controller_cleanup();
 }
 
-static struct platform_driver i8042_driver = {
-	.suspend	= i8042_suspend,
-	.resume		= i8042_resume,
-	.shutdown	= i8042_shutdown,
-	.driver		= {
-		.name	= "i8042",
-	},
-};
-
-static int __init i8042_create_kbd_port(void)
+static int __devinit i8042_create_kbd_port(void)
 {
 	struct serio *serio;
 	struct i8042_port *port = &i8042_ports[I8042_KBD_PORT_NO];
@@ -1003,7 +993,7 @@
 	return i8042_port_register(port);
 }
 
-static int __init i8042_create_aux_port(void)
+static int __devinit i8042_create_aux_port(void)
 {
 	struct serio *serio;
 	struct i8042_port *port = &i8042_ports[I8042_AUX_PORT_NO];
@@ -1028,7 +1018,7 @@
 	return i8042_port_register(port);
 }
 
-static int __init i8042_create_mux_port(int index)
+static int __devinit i8042_create_mux_port(int index)
 {
 	struct serio *serio;
 	struct i8042_port *port = &i8042_ports[I8042_MUX_PORT_NO + index];
@@ -1057,37 +1047,16 @@
 	return i8042_port_register(port);
 }
 
-static int __init i8042_init(void)
+static int __devinit i8042_probe(struct platform_device *dev)
 {
 	int i, have_ports = 0;
 	int err;
 
-	dbg_init();
-
 	init_timer(&i8042_timer);
 	i8042_timer.function = i8042_timer_func;
 
-	err = i8042_platform_init();
-	if (err)
-		return err;
-
-	i8042_ports[I8042_AUX_PORT_NO].irq = I8042_AUX_IRQ;
-	i8042_ports[I8042_KBD_PORT_NO].irq = I8042_KBD_IRQ;
-
-	if (i8042_controller_init()) {
-		err = -ENODEV;
-		goto err_platform_exit;
-	}
-
-	err = platform_driver_register(&i8042_driver);
-	if (err)
-		goto err_controller_cleanup;
-
-	i8042_platform_device = platform_device_register_simple("i8042", -1, NULL, 0);
-	if (IS_ERR(i8042_platform_device)) {
-		err = PTR_ERR(i8042_platform_device);
-		goto err_unregister_driver;
-	}
+	if (i8042_controller_init())
+		return -ENODEV;
 
 	if (!i8042_noaux && !i8042_check_aux()) {
 		if (!i8042_nomux && !i8042_check_mux()) {
@@ -1113,30 +1082,23 @@
 
 	if (!have_ports) {
 		err = -ENODEV;
-		goto err_unregister_device;
+		goto err_controller_cleanup;
 	}
 
 	mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD);
-
 	return 0;
 
  err_unregister_ports:
 	for (i = 0; i < I8042_NUM_PORTS; i++)
 		if (i8042_ports[i].serio)
 			serio_unregister_port(i8042_ports[i].serio);
- err_unregister_device:
-	platform_device_unregister(i8042_platform_device);
- err_unregister_driver:
-	platform_driver_unregister(&i8042_driver);
  err_controller_cleanup:
 	i8042_controller_cleanup();
- err_platform_exit:
-	i8042_platform_exit();
 
 	return err;
 }
 
-static void __exit i8042_exit(void)
+static int __devexit i8042_remove(struct platform_device *dev)
 {
 	int i;
 
@@ -1148,6 +1110,62 @@
 
 	del_timer_sync(&i8042_timer);
 
+	return 0;
+}
+
+static struct platform_driver i8042_driver = {
+	.driver		= {
+		.name	= "i8042",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= i8042_probe,
+	.remove		= __devexit_p(i8042_remove),
+	.suspend	= i8042_suspend,
+	.resume		= i8042_resume,
+	.shutdown	= i8042_shutdown,
+};
+
+static int __init i8042_init(void)
+{
+	int err;
+
+	dbg_init();
+
+	err = i8042_platform_init();
+	if (err)
+		return err;
+
+	i8042_ports[I8042_AUX_PORT_NO].irq = I8042_AUX_IRQ;
+	i8042_ports[I8042_KBD_PORT_NO].irq = I8042_KBD_IRQ;
+
+	err = platform_driver_register(&i8042_driver);
+	if (err)
+		goto err_platform_exit;
+
+	i8042_platform_device = platform_device_alloc("i8042", -1);
+	if (!i8042_platform_device) {
+		err = -ENOMEM;
+		goto err_unregister_driver;
+	}
+
+	err = platform_device_add(i8042_platform_device);
+	if (err)
+		goto err_free_device;
+
+	return 0;
+
+ err_free_device:
+	platform_device_put(i8042_platform_device);
+ err_unregister_driver:
+	platform_driver_unregister(&i8042_driver);
+ err_platform_exit:
+	i8042_platform_exit();
+
+	return err;
+}
+
+static void __exit i8042_exit(void)
+{
 	platform_device_unregister(i8042_platform_device);
 	platform_driver_unregister(&i8042_driver);
 
diff --git a/drivers/input/serio/maceps2.c b/drivers/input/serio/maceps2.c
index d857f70..f08a5d0 100644
--- a/drivers/input/serio/maceps2.c
+++ b/drivers/input/serio/maceps2.c
@@ -118,13 +118,12 @@
 }
 
 
-static struct serio * __init maceps2_allocate_port(int idx)
+static struct serio * __devinit maceps2_allocate_port(int idx)
 {
 	struct serio *serio;
 
-	serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
+	serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
 	if (serio) {
-		memset(serio, 0, sizeof(struct serio));
 		serio->id.type		= SERIO_8042;
 		serio->write		= maceps2_write;
 		serio->open		= maceps2_open;
@@ -138,24 +137,13 @@
 	return serio;
 }
 
-
-static int __init maceps2_init(void)
+static int __devinit maceps2_probe(struct platform_device *dev)
 {
-	maceps2_device = platform_device_register_simple("maceps2", -1, NULL, 0);
-	if (IS_ERR(maceps2_device))
-		return PTR_ERR(maceps2_device);
-
-	port_data[0].port = &mace->perif.ps2.keyb;
-	port_data[0].irq  = MACEISA_KEYB_IRQ;
-	port_data[1].port = &mace->perif.ps2.mouse;
-	port_data[1].irq  = MACEISA_MOUSE_IRQ;
-
 	maceps2_port[0] = maceps2_allocate_port(0);
 	maceps2_port[1] = maceps2_allocate_port(1);
 	if (!maceps2_port[0] || !maceps2_port[1]) {
 		kfree(maceps2_port[0]);
 		kfree(maceps2_port[1]);
-		platform_device_unregister(maceps2_device);
 		return -ENOMEM;
 	}
 
@@ -165,11 +153,59 @@
 	return 0;
 }
 
-static void __exit maceps2_exit(void)
+static int __devexit maceps2_remove(struct platform_device *dev)
 {
 	serio_unregister_port(maceps2_port[0]);
 	serio_unregister_port(maceps2_port[1]);
+
+	return 0;
+}
+
+static struct platform_driver maceps2_driver = {
+	.driver		= {
+		.name	= "maceps2",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= maceps2_probe,
+	.remove		= __devexit_p(maceps2_remove),
+};
+
+static int __init maceps2_init(void)
+{
+	int error;
+
+	error = platform_driver_register(&maceps2_driver);
+	if (error)
+		return error;
+
+	maceps2_device = platform_device_alloc("maceps2", -1);
+	if (!maceps2_device) {
+		error = -ENOMEM;
+		goto err_unregister_driver;
+	}
+
+	port_data[0].port = &mace->perif.ps2.keyb;
+	port_data[0].irq  = MACEISA_KEYB_IRQ;
+	port_data[1].port = &mace->perif.ps2.mouse;
+	port_data[1].irq  = MACEISA_MOUSE_IRQ;
+
+	error = platform_device_add(maceps2_device);
+	if (error)
+		goto err_free_device;
+
+	return 0;
+
+ err_free_device:
+	platform_device_put(maceps2_device);
+ err_unregister_driver:
+	platform_driver_unregister(&maceps2_driver);
+	return error;
+}
+
+static void __exit maceps2_exit(void)
+{
 	platform_device_unregister(maceps2_device);
+	platform_driver_unregister(&maceps2_driver);
 }
 
 module_init(maceps2_init);
diff --git a/drivers/input/serio/q40kbd.c b/drivers/input/serio/q40kbd.c
index b44d255..d3827c5 100644
--- a/drivers/input/serio/q40kbd.c
+++ b/drivers/input/serio/q40kbd.c
@@ -75,13 +75,13 @@
 
 static void q40kbd_flush(void)
 {
- 	int maxread = 100;
+	int maxread = 100;
 	unsigned long flags;
 
 	spin_lock_irqsave(&q40kbd_lock, flags);
 
- 	while (maxread-- && (Q40_IRQ_KEYB_MASK & master_inb(INTERRUPT_REG)))
- 		master_inb(KEYCODE_REG);
+	while (maxread-- && (Q40_IRQ_KEYB_MASK & master_inb(INTERRUPT_REG)))
+		master_inb(KEYCODE_REG);
 
 	spin_unlock_irqrestore(&q40kbd_lock, flags);
 }
@@ -97,14 +97,14 @@
 
 	if (request_irq(Q40_IRQ_KEYBOARD, q40kbd_interrupt, 0, "q40kbd", NULL)) {
 		printk(KERN_ERR "q40kbd.c: Can't get irq %d.\n", Q40_IRQ_KEYBOARD);
-		return -1;
+		return -EBUSY;
 	}
 
- 	/* off we go */
- 	master_outb(-1, KEYBOARD_UNLOCK_REG);
- 	master_outb(1, KEY_IRQ_ENABLE_REG);
+	/* off we go */
+	master_outb(-1, KEYBOARD_UNLOCK_REG);
+	master_outb(1, KEY_IRQ_ENABLE_REG);
 
- 	return 0;
+	return 0;
 }
 
 static void q40kbd_close(struct serio *port)
@@ -116,37 +116,18 @@
 	q40kbd_flush();
 }
 
-static struct serio * __init q40kbd_allocate_port(void)
+static int __devinit q40kbd_probe(struct platform_device *dev)
 {
-	struct serio *serio;
-
-	serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
-	if (serio) {
-		memset(serio, 0, sizeof(struct serio));
-		serio->id.type		= SERIO_8042;
-		serio->open		= q40kbd_open;
-		serio->close		= q40kbd_close;
-		serio->dev.parent	= &q40kbd_device->dev;
-		strlcpy(serio->name, "Q40 Kbd Port", sizeof(serio->name));
-		strlcpy(serio->phys, "Q40", sizeof(serio->phys));
-	}
-
-	return serio;
-}
-
-static int __init q40kbd_init(void)
-{
-	if (!MACH_IS_Q40)
-		return -EIO;
-
-	q40kbd_device = platform_device_register_simple("q40kbd", -1, NULL, 0);
-	if (IS_ERR(q40kbd_device))
-		return PTR_ERR(q40kbd_device);
-
-	if (!(q40kbd_port = q40kbd_allocate_port())) {
-		platform_device_unregister(q40kbd_device);
+	q40kbd_port = kzalloc(sizeof(struct serio), GFP_KERNEL);
+	if (!q40kbd_port)
 		return -ENOMEM;
-	}
+
+	q40kbd_port->id.type	= SERIO_8042;
+	q40kbd_port->open	= q40kbd_open;
+	q40kbd_port->close	= q40kbd_close;
+	q40kbd_port->dev.parent	= &dev->dev;
+	strlcpy(q40kbd_port->name, "Q40 Kbd Port", sizeof(q40kbd_port->name));
+	strlcpy(q40kbd_port->phys, "Q40", sizeof(q40kbd_port->phys));
 
 	serio_register_port(q40kbd_port);
 	printk(KERN_INFO "serio: Q40 kbd registered\n");
@@ -154,10 +135,54 @@
 	return 0;
 }
 
-static void __exit q40kbd_exit(void)
+static int __devexit q40kbd_remove(struct platform_device *dev)
 {
 	serio_unregister_port(q40kbd_port);
+
+	return 0;
+}
+
+static struct platform_driver q40kbd_driver = {
+	.driver		= {
+		.name	= "q40kbd",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= q40kbd_probe,
+	.remove		= __devexit_p(q40kbd_remove),
+};
+
+static int __init q40kbd_init(void)
+{
+	int error;
+
+	if (!MACH_IS_Q40)
+		return -EIO;
+
+	error = platform_driver_register(&q40kbd_driver);
+	if (error)
+		return error;
+
+	q40kbd_device = platform_device_alloc("q40kbd", -1);
+	if (!q40kbd_device)
+		goto err_unregister_driver;
+
+	error = platform_device_add(q40kbd_device);
+	if (error)
+		goto err_free_device;
+
+	return 0;
+
+ err_free_device:
+	platform_device_put(q40kbd_device);
+ err_unregister_driver:
+	platform_driver_unregister(&q40kbd_driver);
+	return error;
+}
+
+static void __exit q40kbd_exit(void)
+{
 	platform_device_unregister(q40kbd_device);
+	platform_driver_unregister(&q40kbd_driver);
 }
 
 module_init(q40kbd_init);
diff --git a/drivers/misc/ibmasm/ibmasm.h b/drivers/misc/ibmasm/ibmasm.h
index d7e20a3..1cef238 100644
--- a/drivers/misc/ibmasm/ibmasm.h
+++ b/drivers/misc/ibmasm/ibmasm.h
@@ -141,8 +141,8 @@
 };
 
 struct ibmasm_remote {
-	struct input_dev keybd_dev;
-	struct input_dev mouse_dev;
+	struct input_dev *keybd_dev;
+	struct input_dev *mouse_dev;
 };
 
 struct service_processor {
@@ -157,7 +157,7 @@
 	char			dirname[IBMASM_NAME_SIZE];
 	char			devname[IBMASM_NAME_SIZE];
 	unsigned int		number;
-	struct ibmasm_remote	*remote;
+	struct ibmasm_remote	remote;
 	int			serial_line;
 	struct device		*dev;
 };
diff --git a/drivers/misc/ibmasm/remote.c b/drivers/misc/ibmasm/remote.c
index d3c48d2..1abd0c5 100644
--- a/drivers/misc/ibmasm/remote.c
+++ b/drivers/misc/ibmasm/remote.c
@@ -203,9 +203,9 @@
 
 		print_input(&input);
 		if (input.type == INPUT_TYPE_MOUSE) {
-			send_mouse_event(&sp->remote->mouse_dev, regs, &input);
+			send_mouse_event(sp->remote.mouse_dev, regs, &input);
 		} else if (input.type == INPUT_TYPE_KEYBOARD) {
-			send_keyboard_event(&sp->remote->keybd_dev, regs, &input);
+			send_keyboard_event(sp->remote.keybd_dev, regs, &input);
 		} else
 			break;
 
@@ -217,56 +217,70 @@
 int ibmasm_init_remote_input_dev(struct service_processor *sp)
 {
 	/* set up the mouse input device */
-	struct ibmasm_remote *remote;
+	struct input_dev *mouse_dev, *keybd_dev;
 	struct pci_dev *pdev = to_pci_dev(sp->dev);
+	int error = -ENOMEM;
 	int i;
 
-	sp->remote = remote = kmalloc(sizeof(*remote), GFP_KERNEL);
-	if (!remote)
-		return -ENOMEM;
+	sp->remote.mouse_dev = mouse_dev = input_allocate_device();
+	sp->remote.keybd_dev = keybd_dev = input_allocate_device();
 
-	memset(remote, 0, sizeof(*remote));
+	if (!mouse_dev || !keybd_dev)
+		goto err_free_devices;
 
-	remote->mouse_dev.private = remote;
-	init_input_dev(&remote->mouse_dev);
-	remote->mouse_dev.id.vendor = pdev->vendor;
-	remote->mouse_dev.id.product = pdev->device;
-	remote->mouse_dev.evbit[0]  = BIT(EV_KEY) | BIT(EV_ABS);
-	remote->mouse_dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) |
+	mouse_dev->id.bustype = BUS_PCI;
+	mouse_dev->id.vendor = pdev->vendor;
+	mouse_dev->id.product = pdev->device;
+	mouse_dev->id.version = 1;
+	mouse_dev->evbit[0]  = BIT(EV_KEY) | BIT(EV_ABS);
+	mouse_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) |
 		BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
-	set_bit(BTN_TOUCH, remote->mouse_dev.keybit);
-	remote->mouse_dev.name = remote_mouse_name;
-	input_set_abs_params(&remote->mouse_dev, ABS_X, 0, xmax, 0, 0);
-	input_set_abs_params(&remote->mouse_dev, ABS_Y, 0, ymax, 0, 0);
+	set_bit(BTN_TOUCH, mouse_dev->keybit);
+	mouse_dev->name = remote_mouse_name;
+	input_set_abs_params(mouse_dev, ABS_X, 0, xmax, 0, 0);
+	input_set_abs_params(mouse_dev, ABS_Y, 0, ymax, 0, 0);
 
-	remote->keybd_dev.private = remote;
-	init_input_dev(&remote->keybd_dev);
-	remote->keybd_dev.id.vendor = pdev->vendor;
-	remote->keybd_dev.id.product = pdev->device;
-	remote->keybd_dev.evbit[0]  = BIT(EV_KEY);
-	remote->keybd_dev.name = remote_keybd_name;
+	mouse_dev->id.bustype = BUS_PCI;
+	keybd_dev->id.vendor = pdev->vendor;
+	keybd_dev->id.product = pdev->device;
+	mouse_dev->id.version = 2;
+	keybd_dev->evbit[0]  = BIT(EV_KEY);
+	keybd_dev->name = remote_keybd_name;
 
-	for (i=0; i<XLATE_SIZE; i++) {
+	for (i = 0; i < XLATE_SIZE; i++) {
 		if (xlate_high[i])
-			set_bit(xlate_high[i], remote->keybd_dev.keybit);
+			set_bit(xlate_high[i], keybd_dev->keybit);
 		if (xlate[i])
-			set_bit(xlate[i], remote->keybd_dev.keybit);
+			set_bit(xlate[i], keybd_dev->keybit);
 	}
 
-	input_register_device(&remote->mouse_dev);
-	input_register_device(&remote->keybd_dev);
+	error = input_register_device(mouse_dev);
+	if (error)
+		goto err_free_devices;
+
+	error = input_register_device(keybd_dev);
+	if (error)
+		goto err_unregister_mouse_dev;
+
 	enable_mouse_interrupts(sp);
 
 	printk(KERN_INFO "ibmasm remote responding to events on RSA card %d\n", sp->number);
 
 	return 0;
+
+ err_unregister_mouse_dev:
+	input_unregister_device(mouse_dev);
+ err_free_devices:
+	input_free_device(mouse_dev);
+	input_free_device(keybd_dev);
+
+	return error;
 }
 
 void ibmasm_free_remote_input_dev(struct service_processor *sp)
 {
 	disable_mouse_interrupts(sp);
-	input_unregister_device(&sp->remote->keybd_dev);
-	input_unregister_device(&sp->remote->mouse_dev);
-	kfree(sp->remote);
+	input_unregister_device(sp->remote.mouse_dev);
+	input_unregister_device(sp->remote.keybd_dev);
 }
 
diff --git a/drivers/usb/input/appletouch.c b/drivers/usb/input/appletouch.c
index 1949b54..c222ed1 100644
--- a/drivers/usb/input/appletouch.c
+++ b/drivers/usb/input/appletouch.c
@@ -6,6 +6,7 @@
  * Copyright (C) 2005      Stelian Pop (stelian@popies.net)
  * Copyright (C) 2005      Frank Arnold (frank@scirocco-5v-turbo.de)
  * Copyright (C) 2005      Peter Osterlund (petero2@telia.com)
+ * Copyright (C) 2005      Michael Hanselmann (linux-kernel@hansmi.ch)
  *
  * Thanks to Alex Harper <basilisk@foobox.net> for his inputs.
  *
@@ -38,6 +39,11 @@
 /* Apple has powerbooks which have the keyboard with different Product IDs */
 #define APPLE_VENDOR_ID		0x05AC
 
+/* These names come from Info.plist in AppleUSBTrackpad.kext */
+#define GEYSER_ANSI_PRODUCT_ID	0x0214
+#define GEYSER_ISO_PRODUCT_ID	0x0215
+#define GEYSER_JIS_PRODUCT_ID	0x0216
+
 #define ATP_DEVICE(prod)					\
 	.match_flags = USB_DEVICE_ID_MATCH_DEVICE |		\
 		       USB_DEVICE_ID_MATCH_INT_CLASS |		\
@@ -53,13 +59,17 @@
 	{ ATP_DEVICE(0x020F) },
 	{ ATP_DEVICE(0x030A) },
 	{ ATP_DEVICE(0x030B) },
-	{ }					/* Terminating entry */
+
+	/* PowerBooks Oct 2005 */
+	{ ATP_DEVICE(GEYSER_ANSI_PRODUCT_ID) },
+	{ ATP_DEVICE(GEYSER_ISO_PRODUCT_ID) },
+	{ ATP_DEVICE(GEYSER_JIS_PRODUCT_ID) },
+
+	/* Terminating entry */
+	{ }
 };
 MODULE_DEVICE_TABLE (usb, atp_table);
 
-/* size of a USB urb transfer */
-#define ATP_DATASIZE	81
-
 /*
  * number of sensors. Note that only 16 instead of 26 X (horizontal)
  * sensors exist on 12" and 15" PowerBooks. All models have 16 Y
@@ -108,6 +118,8 @@
 	signed char		xy_old[ATP_XSENSORS + ATP_YSENSORS];
 						/* accumulated sensors */
 	int			xy_acc[ATP_XSENSORS + ATP_YSENSORS];
+	int			overflowwarn;	/* overflow warning printed? */
+	int			datalen;	/* size of an USB urb transfer */
 };
 
 #define dbg_dump(msg, tab) \
@@ -124,7 +136,7 @@
 		if (debug) printk(format, ##a);				\
 	} while (0)
 
-MODULE_AUTHOR("Johannes Berg, Stelian Pop, Frank Arnold");
+MODULE_AUTHOR("Johannes Berg, Stelian Pop, Frank Arnold, Michael Hanselmann");
 MODULE_DESCRIPTION("Apple PowerBooks USB touchpad driver");
 MODULE_LICENSE("GPL");
 
@@ -132,6 +144,16 @@
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Activate debugging output");
 
+/* Checks if the device a Geyser 2 (ANSI, ISO, JIS) */
+static inline int atp_is_geyser_2(struct atp *dev)
+{
+	int16_t productId = le16_to_cpu(dev->udev->descriptor.idProduct);
+
+	return (productId == GEYSER_ANSI_PRODUCT_ID) ||
+		(productId == GEYSER_ISO_PRODUCT_ID) ||
+		(productId == GEYSER_JIS_PRODUCT_ID);
+}
+
 static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact,
 			     int *z, int *fingers)
 {
@@ -168,13 +190,20 @@
 static void atp_complete(struct urb* urb, struct pt_regs* regs)
 {
 	int x, y, x_z, y_z, x_f, y_f;
-	int retval, i;
+	int retval, i, j;
 	struct atp *dev = urb->context;
 
 	switch (urb->status) {
 	case 0:
 		/* success */
 		break;
+	case -EOVERFLOW:
+		if(!dev->overflowwarn) {
+			printk("appletouch: OVERFLOW with data "
+				"length %d, actual length is %d\n",
+				dev->datalen, dev->urb->actual_length);
+			dev->overflowwarn = 1;
+		}
 	case -ECONNRESET:
 	case -ENOENT:
 	case -ESHUTDOWN:
@@ -189,23 +218,45 @@
 	}
 
 	/* drop incomplete datasets */
-	if (dev->urb->actual_length != ATP_DATASIZE) {
+	if (dev->urb->actual_length != dev->datalen) {
 		dprintk("appletouch: incomplete data package.\n");
 		goto exit;
 	}
 
 	/* reorder the sensors values */
-	for (i = 0; i < 8; i++) {
-		/* X values */
-		dev->xy_cur[i     ] = dev->data[5 * i +  2];
-		dev->xy_cur[i +  8] = dev->data[5 * i +  4];
-		dev->xy_cur[i + 16] = dev->data[5 * i + 42];
-		if (i < 2)
-			dev->xy_cur[i + 24] = dev->data[5 * i + 44];
+	if (atp_is_geyser_2(dev)) {
+		memset(dev->xy_cur, 0, sizeof(dev->xy_cur));
 
-		/* Y values */
-		dev->xy_cur[i + 26] = dev->data[5 * i +  1];
-		dev->xy_cur[i + 34] = dev->data[5 * i +  3];
+		/*
+		 * The values are laid out like this:
+		 * Y1, Y2, -, Y3, Y4, -, ..., X1, X2, -, X3, X4, -, ...
+		 * '-' is an unused value.
+		 */
+
+		/* read X values */
+		for (i = 0, j = 19; i < 20; i += 2, j += 3) {
+			dev->xy_cur[i] = dev->data[j];
+			dev->xy_cur[i + 1] = dev->data[j + 1];
+		}
+
+		/* read Y values */
+		for (i = 0, j = 1; i < 9; i += 2, j += 3) {
+			dev->xy_cur[ATP_XSENSORS + i] = dev->data[j];
+			dev->xy_cur[ATP_XSENSORS + i + 1] = dev->data[j + 1];
+		}
+	} else {
+		for (i = 0; i < 8; i++) {
+			/* X values */
+			dev->xy_cur[i     ] = dev->data[5 * i +  2];
+			dev->xy_cur[i +  8] = dev->data[5 * i +  4];
+			dev->xy_cur[i + 16] = dev->data[5 * i + 42];
+			if (i < 2)
+				dev->xy_cur[i + 24] = dev->data[5 * i + 44];
+
+			/* Y values */
+			dev->xy_cur[i + 26] = dev->data[5 * i +  1];
+			dev->xy_cur[i + 34] = dev->data[5 * i +  3];
+		}
 	}
 
 	dbg_dump("sample", dev->xy_cur);
@@ -216,16 +267,24 @@
 		dev->x_old = dev->y_old = -1;
 		memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old));
 
-		/* 17" Powerbooks have 10 extra X sensors */
-		for (i = 16; i < ATP_XSENSORS; i++)
-			if (dev->xy_cur[i]) {
-				printk("appletouch: 17\" model detected.\n");
+		/* 17" Powerbooks have extra X sensors */
+		for (i = (atp_is_geyser_2(dev)?15:16); i < ATP_XSENSORS; i++) {
+			if (!dev->xy_cur[i]) continue;
+
+			printk("appletouch: 17\" model detected.\n");
+			if(atp_is_geyser_2(dev))
+				input_set_abs_params(dev->input, ABS_X, 0,
+						     (20 - 1) *
+						     ATP_XFACT - 1,
+						     ATP_FUZZ, 0);
+			else
 				input_set_abs_params(dev->input, ABS_X, 0,
 						     (ATP_XSENSORS - 1) *
 						     ATP_XFACT - 1,
 						     ATP_FUZZ, 0);
-				break;
-			}
+
+			break;
+		}
 
 		goto exit;
 	}
@@ -282,7 +341,8 @@
 		memset(dev->xy_acc, 0, sizeof(dev->xy_acc));
 	}
 
-	input_report_key(dev->input, BTN_LEFT, !!dev->data[80]);
+	input_report_key(dev->input, BTN_LEFT,
+			 !!dev->data[dev->datalen - 1]);
 
 	input_sync(dev->input);
 
@@ -353,6 +413,8 @@
 
 	dev->udev = udev;
 	dev->input = input_dev;
+	dev->overflowwarn = 0;
+	dev->datalen = (atp_is_geyser_2(dev)?64:81);
 
 	dev->urb = usb_alloc_urb(0, GFP_KERNEL);
 	if (!dev->urb) {
@@ -360,7 +422,7 @@
 		goto err_free_devs;
 	}
 
-	dev->data = usb_buffer_alloc(dev->udev, ATP_DATASIZE, GFP_KERNEL,
+	dev->data = usb_buffer_alloc(dev->udev, dev->datalen, GFP_KERNEL,
 				     &dev->urb->transfer_dma);
 	if (!dev->data) {
 		retval = -ENOMEM;
@@ -369,7 +431,7 @@
 
 	usb_fill_int_urb(dev->urb, udev,
 			 usb_rcvintpipe(udev, int_in_endpointAddr),
-			 dev->data, ATP_DATASIZE, atp_complete, dev, 1);
+			 dev->data, dev->datalen, atp_complete, dev, 1);
 
 	usb_make_path(udev, dev->phys, sizeof(dev->phys));
 	strlcat(dev->phys, "/input0", sizeof(dev->phys));
@@ -385,14 +447,25 @@
 
 	set_bit(EV_ABS, input_dev->evbit);
 
-	/*
-	 * 12" and 15" Powerbooks only have 16 x sensors,
-	 * 17" models are detected later.
-	 */
-	input_set_abs_params(input_dev, ABS_X, 0,
-			     (16 - 1) * ATP_XFACT - 1, ATP_FUZZ, 0);
-	input_set_abs_params(input_dev, ABS_Y, 0,
-			     (ATP_YSENSORS - 1) * ATP_YFACT - 1, ATP_FUZZ, 0);
+	if (atp_is_geyser_2(dev)) {
+		/*
+		 * Oct 2005 15" PowerBooks have 15 X sensors, 17" are detected
+		 * later.
+		 */
+		input_set_abs_params(input_dev, ABS_X, 0,
+				     ((15 - 1) * ATP_XFACT) - 1, ATP_FUZZ, 0);
+		input_set_abs_params(input_dev, ABS_Y, 0,
+				     ((9 - 1) * ATP_YFACT) - 1, ATP_FUZZ, 0);
+	} else {
+		/*
+		 * 12" and 15" Powerbooks only have 16 x sensors,
+		 * 17" models are detected later.
+		 */
+		input_set_abs_params(input_dev, ABS_X, 0,
+				     (16 - 1) * ATP_XFACT - 1, ATP_FUZZ, 0);
+		input_set_abs_params(input_dev, ABS_Y, 0,
+				     (ATP_YSENSORS - 1) * ATP_YFACT - 1, ATP_FUZZ, 0);
+	}
 	input_set_abs_params(input_dev, ABS_PRESSURE, 0, ATP_PRESSURE, 0, 0);
 
 	set_bit(EV_KEY, input_dev->evbit);
@@ -427,7 +500,7 @@
 		usb_kill_urb(dev->urb);
 		input_unregister_device(dev->input);
 		usb_free_urb(dev->urb);
-		usb_buffer_free(dev->udev, ATP_DATASIZE,
+		usb_buffer_free(dev->udev, dev->datalen,
 				dev->data, dev->urb->transfer_dma);
 		kfree(dev);
 	}
diff --git a/drivers/usb/input/hid-debug.h b/drivers/usb/input/hid-debug.h
index ceebab9..702c48c 100644
--- a/drivers/usb/input/hid-debug.h
+++ b/drivers/usb/input/hid-debug.h
@@ -681,6 +681,21 @@
 	[KEY_SEND] = "Send",			[KEY_REPLY] = "Reply",
 	[KEY_FORWARDMAIL] = "ForwardMail",	[KEY_SAVE] = "Save",
 	[KEY_DOCUMENTS] = "Documents",
+	[KEY_FN] = "Fn",			[KEY_FN_ESC] = "Fn+ESC",
+	[KEY_FN_1] = "Fn+1",			[KEY_FN_2] = "Fn+2",
+	[KEY_FN_B] = "Fn+B",			[KEY_FN_D] = "Fn+D",
+	[KEY_FN_E] = "Fn+E",			[KEY_FN_F] = "Fn+F",
+	[KEY_FN_S] = "Fn+S",
+	[KEY_FN_F1] = "Fn+F1",			[KEY_FN_F2] = "Fn+F2",
+	[KEY_FN_F3] = "Fn+F3",			[KEY_FN_F4] = "Fn+F4",
+	[KEY_FN_F5] = "Fn+F5",			[KEY_FN_F6] = "Fn+F6",
+	[KEY_FN_F7] = "Fn+F7",			[KEY_FN_F8] = "Fn+F8",
+	[KEY_FN_F9] = "Fn+F9",			[KEY_FN_F10] = "Fn+F10",
+	[KEY_FN_F11] = "Fn+F11",		[KEY_FN_F12] = "Fn+F12",
+	[KEY_KBDILLUMTOGGLE] = "KbdIlluminationToggle",
+	[KEY_KBDILLUMDOWN] = "KbdIlluminationDown",
+	[KEY_KBDILLUMUP] = "KbdIlluminationUp",
+	[KEY_SWITCHVIDEOMODE] = "SwitchVideoMode",
 };
 
 static char *relatives[REL_MAX + 1] = {