sony-laptop: Unify the input subsystem event forwarding

SNC and SPIC events are forwarded to the same input devices
and are thus handled together.

Signed-off-by: Mattia Dongili <malattia@linux.it>
Signed-off-by: Len Brown <len.brown@intel.com>
diff --git a/drivers/misc/sony-laptop.c b/drivers/misc/sony-laptop.c
index b797c8c..cf8d792 100644
--- a/drivers/misc/sony-laptop.c
+++ b/drivers/misc/sony-laptop.c
@@ -97,18 +97,266 @@
 static int compat;		/* = 0 */
 module_param(compat, int, 0444);
 MODULE_PARM_DESC(compat,
-		 "set this if you want to enable backward compatibility mode");
-
-static int force_jog;		/* = 0 */
-module_param(force_jog, int, 0444);
-MODULE_PARM_DESC(force_jog,
-		 "set this if the driver doesn't detect your jogdial");
+		 "set this if you want to enable backward compatibility mode for SPIC");
 
 static unsigned long mask = 0xffffffff;
 module_param(mask, ulong, 0644);
 MODULE_PARM_DESC(mask,
 		 "set this to the mask of event you want to enable (see doc)");
 
+/*********** Input Devices ***********/
+
+#define SONY_LAPTOP_BUF_SIZE	128
+struct sony_laptop_input_s {
+	atomic_t		users;
+	struct input_dev	*jog_dev;
+	struct input_dev	*key_dev;
+	struct kfifo		*fifo;
+	spinlock_t		fifo_lock;
+	struct workqueue_struct	*wq;
+};
+static struct sony_laptop_input_s sony_laptop_input = {
+	.users = ATOMIC_INIT(0),
+};
+
+struct sony_laptop_keypress {
+	struct input_dev *dev;
+	int key;
+};
+
+/* Correspondance table between sonypi events and input layer events */
+static struct {
+	int sonypiev;
+	int inputev;
+} sony_laptop_inputkeys[] = {
+	{ SONYPI_EVENT_CAPTURE_PRESSED,	 	KEY_CAMERA },
+	{ SONYPI_EVENT_FNKEY_ONLY, 		KEY_FN },
+	{ SONYPI_EVENT_FNKEY_ESC, 		KEY_FN_ESC },
+	{ SONYPI_EVENT_FNKEY_F1, 		KEY_FN_F1 },
+	{ SONYPI_EVENT_FNKEY_F2, 		KEY_FN_F2 },
+	{ SONYPI_EVENT_FNKEY_F3, 		KEY_FN_F3 },
+	{ SONYPI_EVENT_FNKEY_F4, 		KEY_FN_F4 },
+	{ SONYPI_EVENT_FNKEY_F5, 		KEY_FN_F5 },
+	{ SONYPI_EVENT_FNKEY_F6, 		KEY_FN_F6 },
+	{ SONYPI_EVENT_FNKEY_F7, 		KEY_FN_F7 },
+	{ SONYPI_EVENT_FNKEY_F8, 		KEY_FN_F8 },
+	{ SONYPI_EVENT_FNKEY_F9,		KEY_FN_F9 },
+	{ SONYPI_EVENT_FNKEY_F10,		KEY_FN_F10 },
+	{ SONYPI_EVENT_FNKEY_F11, 		KEY_FN_F11 },
+	{ SONYPI_EVENT_FNKEY_F12,		KEY_FN_F12 },
+	{ SONYPI_EVENT_FNKEY_1, 		KEY_FN_1 },
+	{ SONYPI_EVENT_FNKEY_2, 		KEY_FN_2 },
+	{ SONYPI_EVENT_FNKEY_D,			KEY_FN_D },
+	{ SONYPI_EVENT_FNKEY_E,			KEY_FN_E },
+	{ SONYPI_EVENT_FNKEY_F,			KEY_FN_F },
+	{ SONYPI_EVENT_FNKEY_S,			KEY_FN_S },
+	{ SONYPI_EVENT_FNKEY_B,			KEY_FN_B },
+	{ SONYPI_EVENT_BLUETOOTH_PRESSED, 	KEY_BLUE },
+	{ SONYPI_EVENT_BLUETOOTH_ON, 		KEY_BLUE },
+	{ SONYPI_EVENT_PKEY_P1, 		KEY_PROG1 },
+	{ SONYPI_EVENT_PKEY_P2, 		KEY_PROG2 },
+	{ SONYPI_EVENT_PKEY_P3, 		KEY_PROG3 },
+	{ SONYPI_EVENT_BACK_PRESSED, 		KEY_BACK },
+	{ SONYPI_EVENT_HELP_PRESSED, 		KEY_HELP },
+	{ SONYPI_EVENT_ZOOM_PRESSED, 		KEY_ZOOM },
+	{ SONYPI_EVENT_THUMBPHRASE_PRESSED, 	BTN_THUMB },
+	{ 0, 0 },
+};
+
+/* release buttons after a short delay if pressed */
+static void do_sony_laptop_release_key(struct work_struct *work)
+{
+	struct sony_laptop_keypress kp;
+
+	while (kfifo_get(sony_laptop_input.fifo, (unsigned char *)&kp,
+			 sizeof(kp)) == sizeof(kp)) {
+		msleep(10);
+		input_report_key(kp.dev, kp.key, 0);
+		input_sync(kp.dev);
+	}
+}
+static DECLARE_WORK(sony_laptop_release_key_work,
+		do_sony_laptop_release_key);
+
+/* forward event to the input subsytem */
+static void sony_laptop_report_input_event(u8 event)
+{
+	struct input_dev *jog_dev = sony_laptop_input.jog_dev;
+	struct input_dev *key_dev = sony_laptop_input.key_dev;
+	struct sony_laptop_keypress kp = { NULL };
+	int i;
+
+	if (event == SONYPI_EVENT_FNKEY_RELEASED) {
+		/* Nothing, not all VAIOs generate this event */
+		return;
+	}
+
+	/* report events */
+	switch (event) {
+	/* jog_dev events */
+	case SONYPI_EVENT_JOGDIAL_UP:
+	case SONYPI_EVENT_JOGDIAL_UP_PRESSED:
+		input_report_rel(jog_dev, REL_WHEEL, 1);
+		input_sync(jog_dev);
+		return;
+
+	case SONYPI_EVENT_JOGDIAL_DOWN:
+	case SONYPI_EVENT_JOGDIAL_DOWN_PRESSED:
+		input_report_rel(jog_dev, REL_WHEEL, -1);
+		input_sync(jog_dev);
+		return;
+
+	/* key_dev events */
+	case SONYPI_EVENT_JOGDIAL_PRESSED:
+		kp.key = BTN_MIDDLE;
+		kp.dev = jog_dev;
+		break;
+
+	default:
+		for (i = 0; sony_laptop_inputkeys[i].sonypiev; i++)
+			if (event == sony_laptop_inputkeys[i].sonypiev) {
+				kp.dev = key_dev;
+				kp.key = sony_laptop_inputkeys[i].inputev;
+				break;
+			}
+		break;
+	}
+
+	if (kp.dev) {
+		input_report_key(kp.dev, kp.key, 1);
+		input_sync(kp.dev);
+		kfifo_put(sony_laptop_input.fifo,
+			  (unsigned char *)&kp, sizeof(kp));
+
+		if (!work_pending(&sony_laptop_release_key_work))
+			queue_work(sony_laptop_input.wq,
+					&sony_laptop_release_key_work);
+	} else
+		dprintk("unknown input event %.2x\n", event);
+}
+
+static int sony_laptop_setup_input(void)
+{
+	struct input_dev *jog_dev;
+	struct input_dev *key_dev;
+	int i;
+	int error;
+
+	/* don't run again if already initialized */
+	if (atomic_add_return(1, &sony_laptop_input.users) > 1)
+		return 0;
+
+	/* kfifo */
+	spin_lock_init(&sony_laptop_input.fifo_lock);
+	sony_laptop_input.fifo =
+		kfifo_alloc(SONY_LAPTOP_BUF_SIZE, GFP_KERNEL,
+			    &sony_laptop_input.fifo_lock);
+	if (IS_ERR(sony_laptop_input.fifo)) {
+		printk(KERN_ERR DRV_PFX "kfifo_alloc failed\n");
+		error = PTR_ERR(sony_laptop_input.fifo);
+		goto err_dec_users;
+	}
+
+	/* init workqueue */
+	sony_laptop_input.wq = create_singlethread_workqueue("sony-laptop");
+	if (!sony_laptop_input.wq) {
+		printk(KERN_ERR DRV_PFX
+				"Unabe to create workqueue.\n");
+		error = -ENXIO;
+		goto err_free_kfifo;
+	}
+
+	/* input keys */
+	key_dev = input_allocate_device();
+	if (!key_dev) {
+		error = -ENOMEM;
+		goto err_destroy_wq;
+	}
+
+	key_dev->name = "Sony Vaio Keys";
+	key_dev->id.bustype = BUS_ISA;
+	key_dev->id.vendor = PCI_VENDOR_ID_SONY;
+
+	/* Initialize the Input Drivers: special keys */
+	key_dev->evbit[0] = BIT(EV_KEY);
+	for (i = 0; sony_laptop_inputkeys[i].sonypiev; i++)
+		if (sony_laptop_inputkeys[i].inputev)
+			set_bit(sony_laptop_inputkeys[i].inputev,
+					key_dev->keybit);
+
+	error = input_register_device(key_dev);
+	if (error)
+		goto err_free_keydev;
+
+	sony_laptop_input.key_dev = key_dev;
+
+	/* jogdial */
+	jog_dev = input_allocate_device();
+	if (!jog_dev) {
+		error = -ENOMEM;
+		goto err_unregister_keydev;
+	}
+
+	jog_dev->name = "Sony Vaio Jogdial";
+	jog_dev->id.bustype = BUS_ISA;
+	jog_dev->id.vendor = PCI_VENDOR_ID_SONY;
+
+	jog_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
+	jog_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_MIDDLE);
+	jog_dev->relbit[0] = BIT(REL_WHEEL);
+
+	error = input_register_device(jog_dev);
+	if (error)
+		goto err_free_jogdev;
+
+	sony_laptop_input.jog_dev = jog_dev;
+
+	return 0;
+
+err_free_jogdev:
+	input_free_device(jog_dev);
+
+err_unregister_keydev:
+	input_unregister_device(key_dev);
+	/* to avoid kref underflow below at input_free_device */
+	key_dev = NULL;
+
+err_free_keydev:
+	input_free_device(key_dev);
+
+err_destroy_wq:
+	destroy_workqueue(sony_laptop_input.wq);
+
+err_free_kfifo:
+	kfifo_free(sony_laptop_input.fifo);
+
+err_dec_users:
+	atomic_dec(&sony_laptop_input.users);
+	return error;
+}
+
+static void sony_laptop_remove_input(void)
+{
+	/* cleanup only after the last user has gone */
+	if (!atomic_dec_and_test(&sony_laptop_input.users))
+		return;
+
+	/* flush workqueue first */
+	flush_workqueue(sony_laptop_input.wq);
+
+	/* destroy input devs */
+	input_unregister_device(sony_laptop_input.key_dev);
+	sony_laptop_input.key_dev = NULL;
+
+	if (sony_laptop_input.jog_dev) {
+		input_unregister_device(sony_laptop_input.jog_dev);
+		sony_laptop_input.jog_dev = NULL;
+	}
+
+	destroy_workqueue(sony_laptop_input.wq);
+	kfifo_free(sony_laptop_input.fifo);
+}
+
 /*********** Platform Device ***********/
 
 static atomic_t sony_pf_users = ATOMIC_INIT(0);
@@ -428,6 +676,7 @@
 static void sony_acpi_notify(acpi_handle handle, u32 event, void *data)
 {
 	dprintk("sony_acpi_notify, event: %d\n", event);
+	sony_laptop_report_input_event(event);
 	acpi_bus_generate_event(sony_nc_acpi_device, 1, event);
 }
 
@@ -490,13 +739,21 @@
 		}
 	}
 
+	/* setup input devices and helper fifo */
+	result = sony_laptop_setup_input();
+	if (result) {
+		printk(KERN_ERR DRV_PFX
+				"Unabe to create input devices.\n");
+		goto outwalk;
+	}
+
 	status = acpi_install_notify_handler(sony_nc_acpi_handle,
 					     ACPI_DEVICE_NOTIFY,
 					     sony_acpi_notify, NULL);
 	if (ACPI_FAILURE(status)) {
 		printk(LOG_PFX "unable to install notify handler\n");
 		result = -ENODEV;
-		goto outwalk;
+		goto outinput;
 	}
 
 	if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "GBRT", &handle))) {
@@ -568,6 +825,7 @@
 		device_remove_file(&sony_pf_device->dev, &item->devattr);
 	}
 	sony_pf_remove();
+
       outbacklight:
 	if (sony_backlight_device)
 		backlight_device_unregister(sony_backlight_device);
@@ -577,6 +835,10 @@
 					    sony_acpi_notify);
 	if (ACPI_FAILURE(status))
 		printk(LOG_PFX "unable to remove notify handler\n");
+
+      outinput:
+	sony_laptop_remove_input();
+
       outwalk:
 	return result;
 }
@@ -602,6 +864,7 @@
 	}
 
 	sony_pf_remove();
+	sony_laptop_remove_input();
 
 	printk(KERN_INFO SONY_NC_DRIVER_NAME " successfully removed\n");
 
@@ -626,13 +889,8 @@
 #define SONYPI_DEVICE_TYPE2	0x00000002
 #define SONYPI_DEVICE_TYPE3	0x00000004
 
-#define SONY_EC_JOGB		0x82
-#define SONY_EC_JOGB_MASK	0x02
-
 #define SONY_PIC_EV_MASK	0xff
 
-#define SONYPI_BUF_SIZE	128
-
 struct sony_pic_ioport {
 	struct acpi_resource_io	io;
 	struct list_head	list;
@@ -650,12 +908,6 @@
 	struct sony_pic_ioport	*cur_ioport;
 	struct list_head	interrupts;
 	struct list_head	ioports;
-
-	struct input_dev	*input_jog_dev;
-	struct input_dev	*input_key_dev;
-	struct kfifo		*input_fifo;
-	spinlock_t		input_fifo_lock;
-	struct workqueue_struct	*sony_pic_wq;
 };
 
 static struct sony_pic_dev spic_dev = {
@@ -929,250 +1181,9 @@
 	return v1;
 }
 
-/*****************
- *
- * INPUT Device
- *
- *****************/
-struct sony_pic_keypress {
-	struct input_dev *dev;
-	int key;
-};
-
-/* Correspondance table between sonypi events and input layer events */
-static struct {
-	int sonypiev;
-	int inputev;
-} sony_pic_inputkeys[] = {
-	{ SONYPI_EVENT_CAPTURE_PRESSED,	 	KEY_CAMERA },
-	{ SONYPI_EVENT_FNKEY_ONLY, 		KEY_FN },
-	{ SONYPI_EVENT_FNKEY_ESC, 		KEY_FN_ESC },
-	{ SONYPI_EVENT_FNKEY_F1, 		KEY_FN_F1 },
-	{ SONYPI_EVENT_FNKEY_F2, 		KEY_FN_F2 },
-	{ SONYPI_EVENT_FNKEY_F3, 		KEY_FN_F3 },
-	{ SONYPI_EVENT_FNKEY_F4, 		KEY_FN_F4 },
-	{ SONYPI_EVENT_FNKEY_F5, 		KEY_FN_F5 },
-	{ SONYPI_EVENT_FNKEY_F6, 		KEY_FN_F6 },
-	{ SONYPI_EVENT_FNKEY_F7, 		KEY_FN_F7 },
-	{ SONYPI_EVENT_FNKEY_F8, 		KEY_FN_F8 },
-	{ SONYPI_EVENT_FNKEY_F9,		KEY_FN_F9 },
-	{ SONYPI_EVENT_FNKEY_F10,		KEY_FN_F10 },
-	{ SONYPI_EVENT_FNKEY_F11, 		KEY_FN_F11 },
-	{ SONYPI_EVENT_FNKEY_F12,		KEY_FN_F12 },
-	{ SONYPI_EVENT_FNKEY_1, 		KEY_FN_1 },
-	{ SONYPI_EVENT_FNKEY_2, 		KEY_FN_2 },
-	{ SONYPI_EVENT_FNKEY_D,			KEY_FN_D },
-	{ SONYPI_EVENT_FNKEY_E,			KEY_FN_E },
-	{ SONYPI_EVENT_FNKEY_F,			KEY_FN_F },
-	{ SONYPI_EVENT_FNKEY_S,			KEY_FN_S },
-	{ SONYPI_EVENT_FNKEY_B,			KEY_FN_B },
-	{ SONYPI_EVENT_BLUETOOTH_PRESSED, 	KEY_BLUE },
-	{ SONYPI_EVENT_BLUETOOTH_ON, 		KEY_BLUE },
-	{ SONYPI_EVENT_PKEY_P1, 		KEY_PROG1 },
-	{ SONYPI_EVENT_PKEY_P2, 		KEY_PROG2 },
-	{ SONYPI_EVENT_PKEY_P3, 		KEY_PROG3 },
-	{ SONYPI_EVENT_BACK_PRESSED, 		KEY_BACK },
-	{ SONYPI_EVENT_HELP_PRESSED, 		KEY_HELP },
-	{ SONYPI_EVENT_ZOOM_PRESSED, 		KEY_ZOOM },
-	{ SONYPI_EVENT_THUMBPHRASE_PRESSED, 	BTN_THUMB },
-	{ 0, 0 },
-};
-
-/* release buttons after a short delay if pressed */
-static void do_sony_pic_release_key(struct work_struct *work)
-{
-	struct sony_pic_keypress kp;
-
-	while (kfifo_get(spic_dev.input_fifo, (unsigned char *)&kp,
-			 sizeof(kp)) == sizeof(kp)) {
-		msleep(10);
-		input_report_key(kp.dev, kp.key, 0);
-		input_sync(kp.dev);
-	}
-}
-static DECLARE_WORK(sony_pic_release_key_work,
-		do_sony_pic_release_key);
-
-/* forward event to the input subsytem */
-static void sony_pic_report_input_event(u8 event)
-{
-	struct input_dev *jog_dev = spic_dev.input_jog_dev;
-	struct input_dev *key_dev = spic_dev.input_key_dev;
-	struct sony_pic_keypress kp = { NULL };
-	int i;
-
-	if (event == SONYPI_EVENT_FNKEY_RELEASED) {
-		/* Nothing, not all VAIOs generate this event */
-		return;
-	}
-
-	/* report jog_dev events */
-	if (jog_dev) {
-		switch (event) {
-		case SONYPI_EVENT_JOGDIAL_UP:
-		case SONYPI_EVENT_JOGDIAL_UP_PRESSED:
-			input_report_rel(jog_dev, REL_WHEEL, 1);
-			input_sync(jog_dev);
-			return;
-
-		case SONYPI_EVENT_JOGDIAL_DOWN:
-		case SONYPI_EVENT_JOGDIAL_DOWN_PRESSED:
-			input_report_rel(jog_dev, REL_WHEEL, -1);
-			input_sync(jog_dev);
-			return;
-
-		default:
-			break;
-		}
-	}
-
-	switch (event) {
-	case SONYPI_EVENT_JOGDIAL_PRESSED:
-		kp.key = BTN_MIDDLE;
-		kp.dev = jog_dev;
-		break;
-
-	default:
-		for (i = 0; sony_pic_inputkeys[i].sonypiev; i++)
-			if (event == sony_pic_inputkeys[i].sonypiev) {
-				kp.dev = key_dev;
-				kp.key = sony_pic_inputkeys[i].inputev;
-				break;
-			}
-		break;
-	}
-
-	if (kp.dev) {
-		input_report_key(kp.dev, kp.key, 1);
-		input_sync(kp.dev);
-		kfifo_put(spic_dev.input_fifo,
-			  (unsigned char *)&kp, sizeof(kp));
-
-		if (!work_pending(&sony_pic_release_key_work))
-			queue_work(spic_dev.sony_pic_wq,
-					&sony_pic_release_key_work);
-	}
-}
-
-static int sony_pic_setup_input(void)
-{
-	struct input_dev *jog_dev;
-	struct input_dev *key_dev;
-	int i;
-	int error;
-	u8 jog_present = 0;
-
-	/* kfifo */
-	spin_lock_init(&spic_dev.input_fifo_lock);
-	spic_dev.input_fifo =
-		kfifo_alloc(SONYPI_BUF_SIZE, GFP_KERNEL,
-			    &spic_dev.input_fifo_lock);
-	if (IS_ERR(spic_dev.input_fifo)) {
-		printk(KERN_ERR "sonypi: kfifo_alloc failed\n");
-		return PTR_ERR(spic_dev.input_fifo);
-	}
-
-	/* init workqueue */
-	spic_dev.sony_pic_wq = create_singlethread_workqueue("sony-pic");
-	if (!spic_dev.sony_pic_wq) {
-		printk(KERN_ERR DRV_PFX
-				"Unabe to create workqueue.\n");
-		error = -ENXIO;
-		goto err_free_kfifo;
-	}
-
-	/* input keys */
-	key_dev = input_allocate_device();
-	if (!key_dev) {
-		error = -ENOMEM;
-		goto err_destroy_wq;
-	}
-
-	key_dev->name = "Sony Vaio Keys";
-	key_dev->id.bustype = BUS_ISA;
-	key_dev->id.vendor = PCI_VENDOR_ID_SONY;
-
-	/* Initialize the Input Drivers: special keys */
-	key_dev->evbit[0] = BIT(EV_KEY);
-	for (i = 0; sony_pic_inputkeys[i].sonypiev; i++)
-		if (sony_pic_inputkeys[i].inputev)
-			set_bit(sony_pic_inputkeys[i].inputev, key_dev->keybit);
-
-	error = input_register_device(key_dev);
-	if (error)
-		goto err_free_keydev;
-
-	spic_dev.input_key_dev = key_dev;
-
-	/* jogdial - really reliable ? */
-	ec_read(SONY_EC_JOGB, &jog_present);
-	if (jog_present & SONY_EC_JOGB_MASK || force_jog) {
-		jog_dev = input_allocate_device();
-		if (!jog_dev) {
-			error = -ENOMEM;
-			goto err_unregister_keydev;
-		}
-
-		jog_dev->name = "Sony Vaio Jogdial";
-		jog_dev->id.bustype = BUS_ISA;
-		jog_dev->id.vendor = PCI_VENDOR_ID_SONY;
-
-		jog_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
-		jog_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_MIDDLE);
-		jog_dev->relbit[0] = BIT(REL_WHEEL);
-
-		error = input_register_device(jog_dev);
-		if (error)
-			goto err_free_jogdev;
-
-		spic_dev.input_jog_dev = jog_dev;
-	}
-
-	return 0;
-
-err_free_jogdev:
-	input_free_device(jog_dev);
-
-err_unregister_keydev:
-	input_unregister_device(key_dev);
-	/* to avoid kref underflow below at input_free_device */
-	key_dev = NULL;
-
-err_free_keydev:
-	input_free_device(key_dev);
-
-err_destroy_wq:
-	destroy_workqueue(spic_dev.sony_pic_wq);
-
-err_free_kfifo:
-	kfifo_free(spic_dev.input_fifo);
-
-	return error;
-}
-
-static void sony_pic_remove_input(void)
-{
-	/* flush workqueue first */
-	flush_workqueue(spic_dev.sony_pic_wq);
-
-	/* destroy input devs */
-	input_unregister_device(spic_dev.input_key_dev);
-	spic_dev.input_key_dev = NULL;
-
-	if (spic_dev.input_jog_dev) {
-		input_unregister_device(spic_dev.input_jog_dev);
-		spic_dev.input_jog_dev = NULL;
-	}
-
-	destroy_workqueue(spic_dev.sony_pic_wq);
-	kfifo_free(spic_dev.input_fifo);
-}
-
-/********************
- *
+/*
  * ACPI callbacks
- *
- ********************/
+ */
 static acpi_status
 sony_pic_read_possible_resource(struct acpi_resource *resource, void *context)
 {
@@ -1409,7 +1420,7 @@
 	return IRQ_HANDLED;
 
 found:
-	sony_pic_report_input_event(device_event);
+	sony_laptop_report_input_event(device_event);
 	acpi_bus_generate_event(spic_dev.acpi_dev, 1, device_event);
 
 	return IRQ_HANDLED;
@@ -1434,7 +1445,7 @@
 	release_region(spic_dev.cur_ioport->io.minimum,
 			spic_dev.cur_ioport->io.address_length);
 
-	sony_pic_remove_input();
+	sony_laptop_remove_input();
 
 	list_for_each_entry_safe(io, tmp_io, &spic_dev.ioports, list) {
 		list_del(&io->list);
@@ -1474,7 +1485,7 @@
 	}
 
 	/* setup input devices and helper fifo */
-	result = sony_pic_setup_input();
+	result = sony_laptop_setup_input();
 	if (result) {
 		printk(KERN_ERR DRV_PFX
 				"Unabe to create input devices.\n");
@@ -1535,7 +1546,7 @@
 			spic_dev.cur_ioport->io.address_length);
 
 err_remove_input:
-	sony_pic_remove_input();
+	sony_laptop_remove_input();
 
 err_free_resources:
 	list_for_each_entry_safe(io, tmp_io, &spic_dev.ioports, list) {