public inbox for linux-acpi@vger.kernel.org
 help / color / mirror / Atom feed
* [patch 0/9] [RFC] sonypi ACPI reimplementation (resend 3)
@ 2007-04-09 17:15 malattia
  0 siblings, 0 replies; 13+ messages in thread
From: malattia @ 2007-04-09 17:15 UTC (permalink / raw)
  To: lenb; +Cc: linux-acpi, akpm, stelian

[Resend 3: hopefully this time it will make to the list and the intended
recipients]

The following patch series is the state of the art of my work toward
reimplementing sonypi into sony-laptop. Most patches are mostly cosmetic
to try to obtain a decent namespace separation between the used
subsystems and the drivers driving the two sony devices (SNC and SPIC).
If suitable it would be nice to start applying to acpi-test so that akpm
gets them in -mm (update: it's already in .21-rc6-mm1).

Len, if you prefer a big large patch or a different series, just ask.
The most interesting patches are probably 0004, 0006 and 0009.
Andrew, the 9th patch is now really against acpi-test (I think the Kconfig hunk
didn't apply correclty).

0001-Remove-ACPI-references-from-variable-and-function-names.patch
0002-prepare-pfdriver-for-multiple-users.patch
0003-introduce-debug-macros.patch
0004-add-sny6001-device-handling-from-sonypi.patch
0005-unify-input-subsystem-event-fwd.patch
0006-add-SNY6001-platform-attributes.patch
0007-sanitize-printk-logs.patch
0008-update-documentation.patch
0009-add-sonypi-compat-code.patch
---
 Documentation/sony-laptop.txt |   25 
 drivers/misc/Kconfig          |   15 
 drivers/misc/sony-laptop.c    | 2019 +++++++++++++++++++++++++++++++++++++-----
 3 files changed, 1842 insertions(+), 217 deletions(-)

-- 
mattia
:wq!

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [patch 1/9] Remove ACPI references from variable and function names.
       [not found] <20070409081903.057292676@linux.it>
@ 2007-04-09 17:18 ` malattia
  2007-04-09 17:20 ` [patch 2/9] Prepare the platform driver for multiple users malattia
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 13+ messages in thread
From: malattia @ 2007-04-09 17:18 UTC (permalink / raw)
  To: lenb; +Cc: linux-acpi, akpm, stelian

[-- Attachment #1: 0001-Remove-ACPI-references-from-variable-and-function-names.patch --]
[-- Type: text/plain, Size: 14851 bytes --]

Signed-off-by: Mattia Dongili <malattia@linux.it>
---
 drivers/misc/sony-laptop.c |  178 ++++++++++++++++++++++----------------------
 1 files changed, 89 insertions(+), 89 deletions(-)

Index: linux-2.6/drivers/misc/sony-laptop.c
===================================================================
--- linux-2.6.orig/drivers/misc/sony-laptop.c	2007-03-16 16:03:25.973578562 +0100
+++ linux-2.6/drivers/misc/sony-laptop.c	2007-03-16 16:08:17.490191147 +0100
@@ -35,9 +35,9 @@
 #include <acpi/acpi_bus.h>
 #include <asm/uaccess.h>
 
-#define ACPI_SNC_CLASS		"sony"
-#define ACPI_SNC_HID		"SNY5001"
-#define ACPI_SNC_DRIVER_NAME	"ACPI Sony Notebook Control Driver v0.4"
+#define SONY_NC_CLASS		"sony"
+#define SONY_NC_HID		"SNY5001"
+#define SONY_NC_DRIVER_NAME	"ACPI Sony Notebook Control Driver v0.4"
 
 /* the device uses 1-based values, while the backlight subsystem uses
    0-based values */
@@ -46,7 +46,7 @@
 #define LOG_PFX			KERN_WARNING "sony-laptop: "
 
 MODULE_AUTHOR("Stelian Pop, Mattia Dongili");
-MODULE_DESCRIPTION(ACPI_SNC_DRIVER_NAME);
+MODULE_DESCRIPTION(SONY_NC_DRIVER_NAME);
 MODULE_LICENSE("GPL");
 
 static int debug;
@@ -54,9 +54,9 @@ module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "set this to 1 (and RTFM) if you want to help "
 		 "the development of this driver");
 
-static ssize_t sony_acpi_show(struct device *, struct device_attribute *,
+static ssize_t sony_nc_sysfs_show(struct device *, struct device_attribute *,
 			      char *);
-static ssize_t sony_acpi_store(struct device *, struct device_attribute *,
+static ssize_t sony_nc_sysfs_store(struct device *, struct device_attribute *,
 			       const char *, size_t);
 static int boolean_validate(const int, const int);
 static int brightness_default_validate(const int, const int);
@@ -64,7 +64,7 @@ static int brightness_default_validate(c
 #define SNC_VALIDATE_IN		0
 #define SNC_VALIDATE_OUT	1
 
-struct sony_acpi_value {
+struct sony_nc_value {
 	char *name;		/* name of the entry */
 	char **acpiget;		/* names of the ACPI get function */
 	char **acpiset;		/* names of the ACPI set function */
@@ -75,65 +75,65 @@ struct sony_acpi_value {
 	struct device_attribute devattr;	/* sysfs atribute */
 };
 
-#define HANDLE_NAMES(_name, _values...) \
+#define SNC_HANDLE_NAMES(_name, _values...) \
 	static char *snc_##_name[] = { _values, NULL }
 
-#define SONY_ACPI_VALUE(_name, _getters, _setters, _validate, _debug) \
+#define SNC_HANDLE(_name, _getters, _setters, _validate, _debug) \
 	{ \
 		.name		= __stringify(_name), \
 		.acpiget	= _getters, \
 		.acpiset	= _setters, \
 		.validate	= _validate, \
 		.debug		= _debug, \
-		.devattr	= __ATTR(_name, 0, sony_acpi_show, sony_acpi_store), \
+		.devattr	= __ATTR(_name, 0, sony_nc_sysfs_show, sony_nc_sysfs_store), \
 	}
 
-#define SONY_ACPI_VALUE_NULL	{ .name = NULL }
+#define SNC_HANDLE_NULL	{ .name = NULL }
 
-HANDLE_NAMES(fnkey_get, "GHKE");
+SNC_HANDLE_NAMES(fnkey_get, "GHKE");
 
-HANDLE_NAMES(brightness_def_get, "GPBR");
-HANDLE_NAMES(brightness_def_set, "SPBR");
+SNC_HANDLE_NAMES(brightness_def_get, "GPBR");
+SNC_HANDLE_NAMES(brightness_def_set, "SPBR");
 
-HANDLE_NAMES(cdpower_get, "GCDP");
-HANDLE_NAMES(cdpower_set, "SCDP", "CDPW");
+SNC_HANDLE_NAMES(cdpower_get, "GCDP");
+SNC_HANDLE_NAMES(cdpower_set, "SCDP", "CDPW");
 
-HANDLE_NAMES(audiopower_get, "GAZP");
-HANDLE_NAMES(audiopower_set, "AZPW");
+SNC_HANDLE_NAMES(audiopower_get, "GAZP");
+SNC_HANDLE_NAMES(audiopower_set, "AZPW");
 
-HANDLE_NAMES(lanpower_get, "GLNP");
-HANDLE_NAMES(lanpower_set, "LNPW");
+SNC_HANDLE_NAMES(lanpower_get, "GLNP");
+SNC_HANDLE_NAMES(lanpower_set, "LNPW");
 
-HANDLE_NAMES(PID_get, "GPID");
+SNC_HANDLE_NAMES(PID_get, "GPID");
 
-HANDLE_NAMES(CTR_get, "GCTR");
-HANDLE_NAMES(CTR_set, "SCTR");
+SNC_HANDLE_NAMES(CTR_get, "GCTR");
+SNC_HANDLE_NAMES(CTR_set, "SCTR");
 
-HANDLE_NAMES(PCR_get, "GPCR");
-HANDLE_NAMES(PCR_set, "SPCR");
+SNC_HANDLE_NAMES(PCR_get, "GPCR");
+SNC_HANDLE_NAMES(PCR_set, "SPCR");
 
-HANDLE_NAMES(CMI_get, "GCMI");
-HANDLE_NAMES(CMI_set, "SCMI");
+SNC_HANDLE_NAMES(CMI_get, "GCMI");
+SNC_HANDLE_NAMES(CMI_set, "SCMI");
 
-static struct sony_acpi_value sony_acpi_values[] = {
-	SONY_ACPI_VALUE(brightness_default, snc_brightness_def_get,
+static struct sony_nc_value sony_nc_values[] = {
+	SNC_HANDLE(brightness_default, snc_brightness_def_get,
 			snc_brightness_def_set, brightness_default_validate, 0),
-	SONY_ACPI_VALUE(fnkey, snc_fnkey_get, NULL, NULL, 0),
-	SONY_ACPI_VALUE(cdpower, snc_cdpower_get, snc_cdpower_set, boolean_validate, 0),
-	SONY_ACPI_VALUE(audiopower, snc_audiopower_get, snc_audiopower_set,
+	SNC_HANDLE(fnkey, snc_fnkey_get, NULL, NULL, 0),
+	SNC_HANDLE(cdpower, snc_cdpower_get, snc_cdpower_set, boolean_validate, 0),
+	SNC_HANDLE(audiopower, snc_audiopower_get, snc_audiopower_set,
 			boolean_validate, 0),
-	SONY_ACPI_VALUE(lanpower, snc_lanpower_get, snc_lanpower_set,
+	SNC_HANDLE(lanpower, snc_lanpower_get, snc_lanpower_set,
 			boolean_validate, 1),
 	/* unknown methods */
-	SONY_ACPI_VALUE(PID, snc_PID_get, NULL, NULL, 1),
-	SONY_ACPI_VALUE(CTR, snc_CTR_get, snc_CTR_set, NULL, 1),
-	SONY_ACPI_VALUE(PCR, snc_PCR_get, snc_PCR_set, NULL, 1),
-	SONY_ACPI_VALUE(CMI, snc_CMI_get, snc_CMI_set, NULL, 1),
-	SONY_ACPI_VALUE_NULL
+	SNC_HANDLE(PID, snc_PID_get, NULL, NULL, 1),
+	SNC_HANDLE(CTR, snc_CTR_get, snc_CTR_set, NULL, 1),
+	SNC_HANDLE(PCR, snc_PCR_get, snc_PCR_set, NULL, 1),
+	SNC_HANDLE(CMI, snc_CMI_get, snc_CMI_set, NULL, 1),
+	SNC_HANDLE_NULL
 };
 
-static acpi_handle sony_acpi_handle;
-static struct acpi_device *sony_acpi_acpi_device = NULL;
+static acpi_handle sony_nc_acpi_handle;
+static struct acpi_device *sony_nc_acpi_device = NULL;
 
 /*
  * acpi_evaluate_object wrappers
@@ -194,7 +194,7 @@ static int acpi_callsetfunc(acpi_handle 
 }
 
 /*
- * sony_acpi_values input/output validate functions
+ * sony_nc_values input/output validate functions
  */
 
 /* brightness_default_validate:
@@ -229,19 +229,19 @@ static int boolean_validate(const int di
 }
 
 /*
- * Sysfs show/store common to all sony_acpi_values
+ * Sysfs show/store common to all sony_nc_values
  */
-static ssize_t sony_acpi_show(struct device *dev, struct device_attribute *attr,
+static ssize_t sony_nc_sysfs_show(struct device *dev, struct device_attribute *attr,
 			      char *buffer)
 {
 	int value;
-	struct sony_acpi_value *item =
-	    container_of(attr, struct sony_acpi_value, devattr);
+	struct sony_nc_value *item =
+	    container_of(attr, struct sony_nc_value, devattr);
 
 	if (!*item->acpiget)
 		return -EIO;
 
-	if (acpi_callgetfunc(sony_acpi_handle, *item->acpiget, &value) < 0)
+	if (acpi_callgetfunc(sony_nc_acpi_handle, *item->acpiget, &value) < 0)
 		return -EIO;
 
 	if (item->validate)
@@ -250,13 +250,13 @@ static ssize_t sony_acpi_show(struct dev
 	return snprintf(buffer, PAGE_SIZE, "%d\n", value);
 }
 
-static ssize_t sony_acpi_store(struct device *dev,
+static ssize_t sony_nc_sysfs_store(struct device *dev,
 			       struct device_attribute *attr,
 			       const char *buffer, size_t count)
 {
 	int value;
-	struct sony_acpi_value *item =
-	    container_of(attr, struct sony_acpi_value, devattr);
+	struct sony_nc_value *item =
+	    container_of(attr, struct sony_nc_value, devattr);
 
 	if (!item->acpiset)
 		return -EIO;
@@ -272,7 +272,7 @@ static ssize_t sony_acpi_store(struct de
 	if (value < 0)
 		return value;
 
-	if (acpi_callsetfunc(sony_acpi_handle, *item->acpiset, value, NULL) < 0)
+	if (acpi_callsetfunc(sony_nc_acpi_handle, *item->acpiset, value, NULL) < 0)
 		return -EIO;
 	item->value = value;
 	item->valid = 1;
@@ -290,10 +290,10 @@ static struct platform_driver sncpf_driv
 };
 static struct platform_device *sncpf_device;
 
-static int sony_snc_pf_add(void)
+static int sony_nc_pf_add(void)
 {
 	acpi_handle handle;
-	struct sony_acpi_value *item;
+	struct sony_nc_value *item;
 	int ret = 0;
 
 	ret = platform_driver_register(&sncpf_driver);
@@ -310,14 +310,14 @@ static int sony_snc_pf_add(void)
 	if (ret)
 		goto out_platform_alloced;
 
-	for (item = sony_acpi_values; item->name; ++item) {
+	for (item = sony_nc_values; item->name; ++item) {
 
 		if (!debug && item->debug)
 			continue;
 
 		/* find the available acpiget as described in the DSDT */
 		for (; item->acpiget && *item->acpiget; ++item->acpiget) {
-			if (ACPI_SUCCESS(acpi_get_handle(sony_acpi_handle,
+			if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle,
 							 *item->acpiget,
 							 &handle))) {
 				if (debug)
@@ -330,7 +330,7 @@ static int sony_snc_pf_add(void)
 
 		/* find the available acpiset as described in the DSDT */
 		for (; item->acpiset && *item->acpiset; ++item->acpiset) {
-			if (ACPI_SUCCESS(acpi_get_handle(sony_acpi_handle,
+			if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle,
 							 *item->acpiset,
 							 &handle))) {
 				if (debug)
@@ -353,7 +353,7 @@ static int sony_snc_pf_add(void)
 	return 0;
 
       out_sysfs:
-	for (item = sony_acpi_values; item->name; ++item) {
+	for (item = sony_nc_values; item->name; ++item) {
 		device_remove_file(&sncpf_device->dev, &item->devattr);
 	}
 	platform_device_del(sncpf_device);
@@ -365,11 +365,11 @@ static int sony_snc_pf_add(void)
 	return ret;
 }
 
-static void sony_snc_pf_remove(void)
+static void sony_nc_pf_remove(void)
 {
-	struct sony_acpi_value *item;
+	struct sony_nc_value *item;
 
-	for (item = sony_acpi_values; item->name; ++item) {
+	for (item = sony_nc_values; item->name; ++item) {
 		device_remove_file(&sncpf_device->dev, &item->devattr);
 	}
 
@@ -383,7 +383,7 @@ static void sony_snc_pf_remove(void)
  */
 static int sony_backlight_update_status(struct backlight_device *bd)
 {
-	return acpi_callsetfunc(sony_acpi_handle, "SBRT",
+	return acpi_callsetfunc(sony_nc_acpi_handle, "SBRT",
 				bd->props.brightness + 1, NULL);
 }
 
@@ -391,7 +391,7 @@ static int sony_backlight_get_brightness
 {
 	int value;
 
-	if (acpi_callgetfunc(sony_acpi_handle, "GBRT", &value))
+	if (acpi_callgetfunc(sony_nc_acpi_handle, "GBRT", &value))
 		return 0;
 	/* brightness levels are 1-based, while backlight ones are 0-based */
 	return value - 1;
@@ -410,7 +410,7 @@ static void sony_acpi_notify(acpi_handle
 {
 	if (debug)
 		printk(LOG_PFX "sony_acpi_notify, event: %d\n", event);
-	acpi_bus_generate_event(sony_acpi_acpi_device, 1, event);
+	acpi_bus_generate_event(sony_nc_acpi_device, 1, event);
 }
 
 static acpi_status sony_walk_callback(acpi_handle handle, u32 level,
@@ -431,16 +431,16 @@ static acpi_status sony_walk_callback(ac
 /*
  * ACPI device
  */
-static int sony_acpi_resume(struct acpi_device *device)
+static int sony_nc_resume(struct acpi_device *device)
 {
-	struct sony_acpi_value *item;
+	struct sony_nc_value *item;
 
-	for (item = sony_acpi_values; item->name; item++) {
+	for (item = sony_nc_values; item->name; item++) {
 		int ret;
 
 		if (!item->valid)
 			continue;
-		ret = acpi_callsetfunc(sony_acpi_handle, *item->acpiset,
+		ret = acpi_callsetfunc(sony_nc_acpi_handle, *item->acpiset,
 				       item->value, NULL);
 		if (ret < 0) {
 			printk("%s: %d\n", __FUNCTION__, ret);
@@ -450,18 +450,18 @@ static int sony_acpi_resume(struct acpi_
 	return 0;
 }
 
-static int sony_acpi_add(struct acpi_device *device)
+static int sony_nc_add(struct acpi_device *device)
 {
 	acpi_status status;
 	int result = 0;
 	acpi_handle handle;
 
-	sony_acpi_acpi_device = device;
+	sony_nc_acpi_device = device;
 
-	sony_acpi_handle = device->handle;
+	sony_nc_acpi_handle = device->handle;
 
 	if (debug) {
-		status = acpi_walk_namespace(ACPI_TYPE_METHOD, sony_acpi_handle,
+		status = acpi_walk_namespace(ACPI_TYPE_METHOD, sony_nc_acpi_handle,
 					     1, sony_walk_callback, NULL, NULL);
 		if (ACPI_FAILURE(status)) {
 			printk(LOG_PFX "unable to walk acpi resources\n");
@@ -470,7 +470,7 @@ static int sony_acpi_add(struct acpi_dev
 		}
 	}
 
-	status = acpi_install_notify_handler(sony_acpi_handle,
+	status = acpi_install_notify_handler(sony_nc_acpi_handle,
 					     ACPI_DEVICE_NOTIFY,
 					     sony_acpi_notify, NULL);
 	if (ACPI_FAILURE(status)) {
@@ -479,7 +479,7 @@ static int sony_acpi_add(struct acpi_dev
 		goto outwalk;
 	}
 
-	if (ACPI_SUCCESS(acpi_get_handle(sony_acpi_handle, "GBRT", &handle))) {
+	if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "GBRT", &handle))) {
 		sony_backlight_device = backlight_device_register("sony", NULL,
 								  NULL,
 								  &sony_backlight_ops);
@@ -497,10 +497,10 @@ static int sony_acpi_add(struct acpi_dev
 
 	}
 
-	if (sony_snc_pf_add())
+	if (sony_nc_pf_add())
 		goto outbacklight;
 
-	printk(KERN_INFO ACPI_SNC_DRIVER_NAME " successfully installed\n");
+	printk(KERN_INFO SONY_NC_DRIVER_NAME " successfully installed\n");
 
 	return 0;
 
@@ -508,7 +508,7 @@ static int sony_acpi_add(struct acpi_dev
 	if (sony_backlight_device)
 		backlight_device_unregister(sony_backlight_device);
 
-	status = acpi_remove_notify_handler(sony_acpi_handle,
+	status = acpi_remove_notify_handler(sony_nc_acpi_handle,
 					    ACPI_DEVICE_NOTIFY,
 					    sony_acpi_notify);
 	if (ACPI_FAILURE(status))
@@ -517,48 +517,48 @@ static int sony_acpi_add(struct acpi_dev
 	return result;
 }
 
-static int sony_acpi_remove(struct acpi_device *device, int type)
+static int sony_nc_remove(struct acpi_device *device, int type)
 {
 	acpi_status status;
 
 	if (sony_backlight_device)
 		backlight_device_unregister(sony_backlight_device);
 
-	sony_acpi_acpi_device = NULL;
+	sony_nc_acpi_device = NULL;
 
-	status = acpi_remove_notify_handler(sony_acpi_handle,
+	status = acpi_remove_notify_handler(sony_nc_acpi_handle,
 					    ACPI_DEVICE_NOTIFY,
 					    sony_acpi_notify);
 	if (ACPI_FAILURE(status))
 		printk(LOG_PFX "unable to remove notify handler\n");
 
-	sony_snc_pf_remove();
+	sony_nc_pf_remove();
 
-	printk(KERN_INFO ACPI_SNC_DRIVER_NAME " successfully removed\n");
+	printk(KERN_INFO SONY_NC_DRIVER_NAME " successfully removed\n");
 
 	return 0;
 }
 
-static struct acpi_driver sony_acpi_driver = {
-	.name = ACPI_SNC_DRIVER_NAME,
-	.class = ACPI_SNC_CLASS,
-	.ids = ACPI_SNC_HID,
+static struct acpi_driver sony_nc_driver = {
+	.name = SONY_NC_DRIVER_NAME,
+	.class = SONY_NC_CLASS,
+	.ids = SONY_NC_HID,
 	.ops = {
-		.add = sony_acpi_add,
-		.remove = sony_acpi_remove,
-		.resume = sony_acpi_resume,
+		.add = sony_nc_add,
+		.remove = sony_nc_remove,
+		.resume = sony_nc_resume,
 		},
 };
 
-static int __init sony_acpi_init(void)
+static int __init sony_laptop_init(void)
 {
-	return acpi_bus_register_driver(&sony_acpi_driver);
+	return acpi_bus_register_driver(&sony_nc_driver);
 }
 
-static void __exit sony_acpi_exit(void)
+static void __exit sony_laptop_exit(void)
 {
-	acpi_bus_unregister_driver(&sony_acpi_driver);
+	acpi_bus_unregister_driver(&sony_nc_driver);
 }
 
-module_init(sony_acpi_init);
-module_exit(sony_acpi_exit);
+module_init(sony_laptop_init);
+module_exit(sony_laptop_exit);

--
-- 
mattia
:wq!

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [patch 2/9] Prepare the platform driver for multiple users.
       [not found] <20070409081903.057292676@linux.it>
  2007-04-09 17:18 ` [patch 1/9] Remove ACPI references from variable and function names malattia
@ 2007-04-09 17:20 ` malattia
  2007-04-09 17:22 ` [patch 3/9] Add debug macros also used by the sonypi reimplementation malattia
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 13+ messages in thread
From: malattia @ 2007-04-09 17:20 UTC (permalink / raw)
  To: lenb; +Cc: linux-acpi, akpm, stelian

[-- Attachment #1: 0002-prepare-pfdriver-for-multiple-users.patch --]
[-- Type: text/plain, Size: 7255 bytes --]

Both the SNC and SPIC device drivers will create attributes and thus
there's the need to have an internal usage count to avoid
re-registering or de-registering at the wrong time.

Signed-off-by: Mattia Dongili <malattia@linux.it>
---
 drivers/misc/sony-laptop.c |  212 ++++++++++++++++++++++++++++++----------------------------
 1 file changed, 112 insertions(+), 100 deletions(-)

Index: linux-2.6/drivers/misc/sony-laptop.c
===================================================================
--- linux-2.6.orig/drivers/misc/sony-laptop.c	2007-03-16 16:08:17.490191147 +0100
+++ linux-2.6/drivers/misc/sony-laptop.c	2007-03-18 18:50:17.769519953 +0100
@@ -54,6 +54,64 @@ module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "set this to 1 (and RTFM) if you want to help "
 		 "the development of this driver");
 
+/*********** Platform Device ***********/
+
+static atomic_t sony_pf_users = ATOMIC_INIT(0);
+static struct platform_driver sony_pf_driver = {
+	.driver = {
+		   .name = "sony-laptop",
+		   .owner = THIS_MODULE,
+		   }
+};
+static struct platform_device *sony_pf_device;
+
+static int sony_pf_add(void)
+{
+	int ret = 0;
+
+	/* don't run again if already initialized */
+	if (atomic_add_return(1, &sony_pf_users) > 1)
+		return 0;
+
+	ret = platform_driver_register(&sony_pf_driver);
+	if (ret)
+		goto out;
+
+	sony_pf_device = platform_device_alloc("sony-laptop", -1);
+	if (!sony_pf_device) {
+		ret = -ENOMEM;
+		goto out_platform_registered;
+	}
+
+	ret = platform_device_add(sony_pf_device);
+	if (ret)
+		goto out_platform_alloced;
+
+	return 0;
+
+      out_platform_alloced:
+	platform_device_put(sony_pf_device);
+	sony_pf_device = NULL;
+      out_platform_registered:
+	platform_driver_unregister(&sony_pf_driver);
+      out:
+	atomic_dec(&sony_pf_users);
+	return ret;
+}
+
+static void sony_pf_remove(void)
+{
+	/* deregister only after the last user has gone */
+	if (!atomic_dec_and_test(&sony_pf_users))
+		return;
+
+	platform_device_del(sony_pf_device);
+	platform_device_put(sony_pf_device);
+	platform_driver_unregister(&sony_pf_driver);
+}
+
+/*********** SNC (SNY5001) Device ***********/
+
 static ssize_t sony_nc_sysfs_show(struct device *, struct device_attribute *,
 			      char *);
 static ssize_t sony_nc_sysfs_store(struct device *, struct device_attribute *,
@@ -279,104 +337,6 @@ static ssize_t sony_nc_sysfs_store(struc
 	return count;
 }
 
-/*
- * Platform device
- */
-static struct platform_driver sncpf_driver = {
-	.driver = {
-		   .name = "sony-laptop",
-		   .owner = THIS_MODULE,
-		   }
-};
-static struct platform_device *sncpf_device;
-
-static int sony_nc_pf_add(void)
-{
-	acpi_handle handle;
-	struct sony_nc_value *item;
-	int ret = 0;
-
-	ret = platform_driver_register(&sncpf_driver);
-	if (ret)
-		goto out;
-
-	sncpf_device = platform_device_alloc("sony-laptop", -1);
-	if (!sncpf_device) {
-		ret = -ENOMEM;
-		goto out_platform_registered;
-	}
-
-	ret = platform_device_add(sncpf_device);
-	if (ret)
-		goto out_platform_alloced;
-
-	for (item = sony_nc_values; item->name; ++item) {
-
-		if (!debug && item->debug)
-			continue;
-
-		/* find the available acpiget as described in the DSDT */
-		for (; item->acpiget && *item->acpiget; ++item->acpiget) {
-			if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle,
-							 *item->acpiget,
-							 &handle))) {
-				if (debug)
-					printk(LOG_PFX "Found %s getter: %s\n",
-					       item->name, *item->acpiget);
-				item->devattr.attr.mode |= S_IRUGO;
-				break;
-			}
-		}
-
-		/* find the available acpiset as described in the DSDT */
-		for (; item->acpiset && *item->acpiset; ++item->acpiset) {
-			if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle,
-							 *item->acpiset,
-							 &handle))) {
-				if (debug)
-					printk(LOG_PFX "Found %s setter: %s\n",
-					       item->name, *item->acpiset);
-				item->devattr.attr.mode |= S_IWUSR;
-				break;
-			}
-		}
-
-		if (item->devattr.attr.mode != 0) {
-			ret =
-			    device_create_file(&sncpf_device->dev,
-					       &item->devattr);
-			if (ret)
-				goto out_sysfs;
-		}
-	}
-
-	return 0;
-
-      out_sysfs:
-	for (item = sony_nc_values; item->name; ++item) {
-		device_remove_file(&sncpf_device->dev, &item->devattr);
-	}
-	platform_device_del(sncpf_device);
-      out_platform_alloced:
-	platform_device_put(sncpf_device);
-      out_platform_registered:
-	platform_driver_unregister(&sncpf_driver);
-      out:
-	return ret;
-}
-
-static void sony_nc_pf_remove(void)
-{
-	struct sony_nc_value *item;
-
-	for (item = sony_nc_values; item->name; ++item) {
-		device_remove_file(&sncpf_device->dev, &item->devattr);
-	}
-
-	platform_device_del(sncpf_device);
-	platform_device_put(sncpf_device);
-	platform_driver_unregister(&sncpf_driver);
-}
 
 /*
  * Backlight device
@@ -455,6 +415,7 @@ static int sony_nc_add(struct acpi_devic
 	acpi_status status;
 	int result = 0;
 	acpi_handle handle;
+	struct sony_nc_value *item;
 
 	sony_nc_acpi_device = device;
 
@@ -497,13 +458,59 @@ static int sony_nc_add(struct acpi_devic
 
 	}
 
-	if (sony_nc_pf_add())
+	if (sony_pf_add())
 		goto outbacklight;
 
+	/* create sony_pf sysfs attributes related to the SNC device */
+	for (item = sony_nc_values; item->name; ++item) {
+
+		if (!debug && item->debug)
+			continue;
+
+		/* find the available acpiget as described in the DSDT */
+		for (; item->acpiget && *item->acpiget; ++item->acpiget) {
+			if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle,
+							 *item->acpiget,
+							 &handle))) {
+				if (debug)
+					printk(LOG_PFX "Found %s getter: %s\n",
+					       item->name, *item->acpiget);
+				item->devattr.attr.mode |= S_IRUGO;
+				break;
+			}
+		}
+
+		/* find the available acpiset as described in the DSDT */
+		for (; item->acpiset && *item->acpiset; ++item->acpiset) {
+			if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle,
+							 *item->acpiset,
+							 &handle))) {
+				if (debug)
+					printk(LOG_PFX "Found %s setter: %s\n",
+					       item->name, *item->acpiset);
+				item->devattr.attr.mode |= S_IWUSR;
+				break;
+			}
+		}
+
+		if (item->devattr.attr.mode != 0) {
+			result =
+			    device_create_file(&sony_pf_device->dev,
+					       &item->devattr);
+			if (result)
+				goto out_sysfs;
+		}
+	}
+
 	printk(KERN_INFO SONY_NC_DRIVER_NAME " successfully installed\n");
 
 	return 0;
 
+      out_sysfs:
+	for (item = sony_nc_values; item->name; ++item) {
+		device_remove_file(&sony_pf_device->dev, &item->devattr);
+	}
+	sony_pf_remove();
       outbacklight:
 	if (sony_backlight_device)
 		backlight_device_unregister(sony_backlight_device);
@@ -520,6 +527,7 @@ static int sony_nc_add(struct acpi_devic
 static int sony_nc_remove(struct acpi_device *device, int type)
 {
 	acpi_status status;
+	struct sony_nc_value *item;
 
 	if (sony_backlight_device)
 		backlight_device_unregister(sony_backlight_device);
@@ -532,7 +540,11 @@ static int sony_nc_remove(struct acpi_de
 	if (ACPI_FAILURE(status))
 		printk(LOG_PFX "unable to remove notify handler\n");
 
-	sony_nc_pf_remove();
+	for (item = sony_nc_values; item->name; ++item) {
+		device_remove_file(&sony_pf_device->dev, &item->devattr);
+	}
+
+	sony_pf_remove();
 
 	printk(KERN_INFO SONY_NC_DRIVER_NAME " successfully removed\n");
 

--
-- 
mattia
:wq!

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [patch 3/9] Add debug macros also used by the sonypi reimplementation
       [not found] <20070409081903.057292676@linux.it>
  2007-04-09 17:18 ` [patch 1/9] Remove ACPI references from variable and function names malattia
  2007-04-09 17:20 ` [patch 2/9] Prepare the platform driver for multiple users malattia
@ 2007-04-09 17:22 ` malattia
  2007-04-09 17:26 ` [patch 4/9] Add SNY6001 device handling (sonypi reimplementation) malattia
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 13+ messages in thread
From: malattia @ 2007-04-09 17:22 UTC (permalink / raw)
  To: lenb; +Cc: linux-acpi, akpm, stelian

[-- Attachment #1: 0003-introduce-debug-macros.patch --]
[-- Type: text/plain, Size: 2179 bytes --]

Signed-off-by: Mattia Dongili <malattia@linux.it>
---
 drivers/misc/sony-laptop.c |   20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

Index: linux-2.6/drivers/misc/sony-laptop.c
===================================================================
--- linux-2.6.orig/drivers/misc/sony-laptop.c	2007-03-18 18:50:17.769519953 +0100
+++ linux-2.6/drivers/misc/sony-laptop.c	2007-03-18 18:50:26.270004320 +0100
@@ -35,6 +35,11 @@
 #include <acpi/acpi_bus.h>
 #include <asm/uaccess.h>
 
+#define LOG_PFX			KERN_WARNING "sony-laptop: "
+#define dprintk(msg...)		do {			\
+	if (debug) printk(KERN_WARNING LOG_PFX  msg);	\
+} while (0)
+
 #define SONY_NC_CLASS		"sony"
 #define SONY_NC_HID		"SNY5001"
 #define SONY_NC_DRIVER_NAME	"ACPI Sony Notebook Control Driver v0.4"
@@ -43,8 +48,6 @@
    0-based values */
 #define SONY_MAX_BRIGHTNESS	8
 
-#define LOG_PFX			KERN_WARNING "sony-laptop: "
-
 MODULE_AUTHOR("Stelian Pop, Mattia Dongili");
 MODULE_DESCRIPTION(SONY_NC_DRIVER_NAME);
 MODULE_LICENSE("GPL");
@@ -368,8 +371,7 @@ static struct backlight_ops sony_backlig
  */
 static void sony_acpi_notify(acpi_handle handle, u32 event, void *data)
 {
-	if (debug)
-		printk(LOG_PFX "sony_acpi_notify, event: %d\n", event);
+	dprintk("sony_acpi_notify, event: %d\n", event);
 	acpi_bus_generate_event(sony_nc_acpi_device, 1, event);
 }
 
@@ -472,9 +474,8 @@ static int sony_nc_add(struct acpi_devic
 			if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle,
 							 *item->acpiget,
 							 &handle))) {
-				if (debug)
-					printk(LOG_PFX "Found %s getter: %s\n",
-					       item->name, *item->acpiget);
+				dprintk("Found %s getter: %s\n",
+						item->name, *item->acpiget);
 				item->devattr.attr.mode |= S_IRUGO;
 				break;
 			}
@@ -485,9 +486,8 @@ static int sony_nc_add(struct acpi_devic
 			if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle,
 							 *item->acpiset,
 							 &handle))) {
-				if (debug)
-					printk(LOG_PFX "Found %s setter: %s\n",
-					       item->name, *item->acpiset);
+				dprintk("Found %s setter: %s\n",
+						item->name, *item->acpiset);
 				item->devattr.attr.mode |= S_IWUSR;
 				break;
 			}

--
-- 
mattia
:wq!

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [patch 4/9] Add SNY6001 device handling (sonypi reimplementation)
       [not found] <20070409081903.057292676@linux.it>
                   ` (2 preceding siblings ...)
  2007-04-09 17:22 ` [patch 3/9] Add debug macros also used by the sonypi reimplementation malattia
@ 2007-04-09 17:26 ` malattia
  2007-04-09 17:28 ` [patch 5/9] Unify the input subsystem event forwarding malattia
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 13+ messages in thread
From: malattia @ 2007-04-09 17:26 UTC (permalink / raw)
  To: lenb; +Cc: linux-acpi, akpm, stelian

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: 0004-add-sny6001-device-handling-from-sonypi.patch --]
[-- Type: text/plain; charset=euc-jp, Size: 34283 bytes --]

Reimplement sonypi using ACPI only functions.

Signed-off-by: Mattia Dongili <malattia@linux.it>
---
 drivers/misc/sony-laptop.c | 1078 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 1065 insertions(+), 13 deletions(-)

Index: linux-2.6/drivers/misc/sony-laptop.c
===================================================================
--- linux-2.6.orig/drivers/misc/sony-laptop.c	2007-03-30 16:43:37.267010350 +0200
+++ linux-2.6/drivers/misc/sony-laptop.c	2007-04-05 19:07:17.516590739 +0200
@@ -1,5 +1,5 @@
 /*
- * ACPI Sony Notebook Control Driver (SNC)
+ * ACPI Sony Notebook Control Driver (SNC and SPIC)
  *
  * Copyright (C) 2004-2005 Stelian Pop <stelian@popies.net>
  * Copyright (C) 2007 Mattia Dongili <malattia@linux.it>
@@ -7,6 +7,25 @@
  * Parts of this driver inspired from asus_acpi.c and ibm_acpi.c
  * which are copyrighted by their respective authors.
  *
+ * The SNY6001 driver part is based on the sonypi driver which includes
+ * material from:
+ *
+ * Copyright (C) 2001-2005 Stelian Pop <stelian@popies.net>
+ *
+ * Copyright (C) 2005 Narayanan R S <nars@kadamba.org>
+ *
+ * Copyright (C) 2001-2002 Alcôve <www.alcove.com>
+ *
+ * Copyright (C) 2001 Michael Ashley <m.ashley@unsw.edu.au>
+ *
+ * Copyright (C) 2001 Junichi Morita <jun1m@mars.dti.ne.jp>
+ *
+ * Copyright (C) 2000 Takaya Kinjo <t-kinjo@tc4.so-net.ne.jp>
+ *
+ * Copyright (C) 2000 Andrew Tridgell <tridge@valinux.com>
+ *
+ * Earlier work by Werner Almesberger, Paul `Rusty' Russell and Paul Mackerras.
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
@@ -31,32 +50,65 @@
 #include <linux/backlight.h>
 #include <linux/platform_device.h>
 #include <linux/err.h>
+#include <linux/dmi.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/input.h>
+#include <linux/kfifo.h>
+#include <linux/workqueue.h>
+#include <linux/acpi.h>
 #include <acpi/acpi_drivers.h>
 #include <acpi/acpi_bus.h>
 #include <asm/uaccess.h>
+#include <linux/sonypi.h>
 
-#define LOG_PFX			KERN_WARNING "sony-laptop: "
+#define DRV_PFX			"sony-laptop: "
+#define LOG_PFX			KERN_WARNING DRV_PFX
 #define dprintk(msg...)		do {			\
-	if (debug) printk(KERN_WARNING LOG_PFX  msg);	\
+	if (debug) printk(LOG_PFX  msg);		\
 } while (0)
 
-#define SONY_NC_CLASS		"sony"
+#define SONY_LAPTOP_DRIVER_VERSION	"0.5"
+
+#define SONY_NC_CLASS		"sony-nc"
 #define SONY_NC_HID		"SNY5001"
-#define SONY_NC_DRIVER_NAME	"ACPI Sony Notebook Control Driver v0.4"
+#define SONY_NC_DRIVER_NAME	"Sony Notebook Control"
 
-/* the device uses 1-based values, while the backlight subsystem uses
-   0-based values */
-#define SONY_MAX_BRIGHTNESS	8
+#define SONY_PIC_CLASS		"sony-pic"
+#define SONY_PIC_HID		"SNY6001"
+#define SONY_PIC_DRIVER_NAME	"Sony Programmable IO Control"
 
 MODULE_AUTHOR("Stelian Pop, Mattia Dongili");
-MODULE_DESCRIPTION(SONY_NC_DRIVER_NAME);
+MODULE_DESCRIPTION("Sony laptop extras driver (SPIC and SNC ACPI device)");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(SONY_LAPTOP_DRIVER_VERSION);
 
 static int debug;
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "set this to 1 (and RTFM) if you want to help "
 		 "the development of this driver");
 
+static int no_spic;		/* = 0 */
+module_param(no_spic, int, 0444);
+MODULE_PARM_DESC(no_spic,
+		 "set this if you don't want to enable the SPIC device");
+
+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");
+
+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)");
+
 /*********** Platform Device ***********/
 
 static atomic_t sony_pf_users = ATOMIC_INIT(0);
@@ -115,6 +167,13 @@ static void sony_pf_remove(void)
 
 /*********** SNC (SNY5001) Device ***********/
 
+/* the device uses 1-based values, while the backlight subsystem uses
+   0-based values */
+#define SONY_MAX_BRIGHTNESS	8
+
+#define SNC_VALIDATE_IN		0
+#define SNC_VALIDATE_OUT	1
+
 static ssize_t sony_nc_sysfs_show(struct device *, struct device_attribute *,
 			      char *);
 static ssize_t sony_nc_sysfs_store(struct device *, struct device_attribute *,
@@ -122,9 +181,6 @@ static ssize_t sony_nc_sysfs_store(struc
 static int boolean_validate(const int, const int);
 static int brightness_default_validate(const int, const int);
 
-#define SNC_VALIDATE_IN		0
-#define SNC_VALIDATE_OUT	1
-
 struct sony_nc_value {
 	char *name;		/* name of the entry */
 	char **acpiget;		/* names of the ACPI get function */
@@ -420,6 +476,7 @@ static int sony_nc_add(struct acpi_devic
 	struct sony_nc_value *item;
 
 	sony_nc_acpi_device = device;
+	strcpy(acpi_device_class(device), "sony/hotkey");
 
 	sony_nc_acpi_handle = device->handle;
 
@@ -555,6 +612,7 @@ static struct acpi_driver sony_nc_driver
 	.name = SONY_NC_DRIVER_NAME,
 	.class = SONY_NC_CLASS,
 	.ids = SONY_NC_HID,
+	.owner = THIS_MODULE,
 	.ops = {
 		.add = sony_nc_add,
 		.remove = sony_nc_remove,
@@ -562,14 +620,1015 @@ static struct acpi_driver sony_nc_driver
 		},
 };
 
+/*********** SPIC (SNY6001) Device ***********/
+
+#define SONYPI_DEVICE_TYPE1	0x00000001
+#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;
+};
+
+struct sony_pic_irq {
+	struct acpi_resource_irq	irq;
+	struct list_head		list;
+};
+
+struct sony_pic_dev {
+	int			model;
+	struct acpi_device	*acpi_dev;
+	struct sony_pic_irq	*cur_irq;
+	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 = {
+	.interrupts	= LIST_HEAD_INIT(spic_dev.interrupts),
+	.ioports	= LIST_HEAD_INIT(spic_dev.ioports),
+};
+
+/* Event masks */
+#define SONYPI_JOGGER_MASK			0x00000001
+#define SONYPI_CAPTURE_MASK			0x00000002
+#define SONYPI_FNKEY_MASK			0x00000004
+#define SONYPI_BLUETOOTH_MASK			0x00000008
+#define SONYPI_PKEY_MASK			0x00000010
+#define SONYPI_BACK_MASK			0x00000020
+#define SONYPI_HELP_MASK			0x00000040
+#define SONYPI_LID_MASK				0x00000080
+#define SONYPI_ZOOM_MASK			0x00000100
+#define SONYPI_THUMBPHRASE_MASK			0x00000200
+#define SONYPI_MEYE_MASK			0x00000400
+#define SONYPI_MEMORYSTICK_MASK			0x00000800
+#define SONYPI_BATTERY_MASK			0x00001000
+#define SONYPI_WIRELESS_MASK			0x00002000
+
+struct sonypi_event {
+	u8	data;
+	u8	event;
+};
+
+/* The set of possible button release events */
+static struct sonypi_event sonypi_releaseev[] = {
+	{ 0x00, SONYPI_EVENT_ANYBUTTON_RELEASED },
+	{ 0, 0 }
+};
+
+/* The set of possible jogger events  */
+static struct sonypi_event sonypi_joggerev[] = {
+	{ 0x1f, SONYPI_EVENT_JOGDIAL_UP },
+	{ 0x01, SONYPI_EVENT_JOGDIAL_DOWN },
+	{ 0x5f, SONYPI_EVENT_JOGDIAL_UP_PRESSED },
+	{ 0x41, SONYPI_EVENT_JOGDIAL_DOWN_PRESSED },
+	{ 0x1e, SONYPI_EVENT_JOGDIAL_FAST_UP },
+	{ 0x02, SONYPI_EVENT_JOGDIAL_FAST_DOWN },
+	{ 0x5e, SONYPI_EVENT_JOGDIAL_FAST_UP_PRESSED },
+	{ 0x42, SONYPI_EVENT_JOGDIAL_FAST_DOWN_PRESSED },
+	{ 0x1d, SONYPI_EVENT_JOGDIAL_VFAST_UP },
+	{ 0x03, SONYPI_EVENT_JOGDIAL_VFAST_DOWN },
+	{ 0x5d, SONYPI_EVENT_JOGDIAL_VFAST_UP_PRESSED },
+	{ 0x43, SONYPI_EVENT_JOGDIAL_VFAST_DOWN_PRESSED },
+	{ 0x40, SONYPI_EVENT_JOGDIAL_PRESSED },
+	{ 0, 0 }
+};
+
+/* The set of possible capture button events */
+static struct sonypi_event sonypi_captureev[] = {
+	{ 0x05, SONYPI_EVENT_CAPTURE_PARTIALPRESSED },
+	{ 0x07, SONYPI_EVENT_CAPTURE_PRESSED },
+	{ 0x01, SONYPI_EVENT_CAPTURE_PARTIALRELEASED },
+	{ 0, 0 }
+};
+
+/* The set of possible fnkeys events */
+static struct sonypi_event sonypi_fnkeyev[] = {
+	{ 0x10, SONYPI_EVENT_FNKEY_ESC },
+	{ 0x11, SONYPI_EVENT_FNKEY_F1 },
+	{ 0x12, SONYPI_EVENT_FNKEY_F2 },
+	{ 0x13, SONYPI_EVENT_FNKEY_F3 },
+	{ 0x14, SONYPI_EVENT_FNKEY_F4 },
+	{ 0x15, SONYPI_EVENT_FNKEY_F5 },
+	{ 0x16, SONYPI_EVENT_FNKEY_F6 },
+	{ 0x17, SONYPI_EVENT_FNKEY_F7 },
+	{ 0x18, SONYPI_EVENT_FNKEY_F8 },
+	{ 0x19, SONYPI_EVENT_FNKEY_F9 },
+	{ 0x1a, SONYPI_EVENT_FNKEY_F10 },
+	{ 0x1b, SONYPI_EVENT_FNKEY_F11 },
+	{ 0x1c, SONYPI_EVENT_FNKEY_F12 },
+	{ 0x1f, SONYPI_EVENT_FNKEY_RELEASED },
+	{ 0x21, SONYPI_EVENT_FNKEY_1 },
+	{ 0x22, SONYPI_EVENT_FNKEY_2 },
+	{ 0x31, SONYPI_EVENT_FNKEY_D },
+	{ 0x32, SONYPI_EVENT_FNKEY_E },
+	{ 0x33, SONYPI_EVENT_FNKEY_F },
+	{ 0x34, SONYPI_EVENT_FNKEY_S },
+	{ 0x35, SONYPI_EVENT_FNKEY_B },
+	{ 0x36, SONYPI_EVENT_FNKEY_ONLY },
+	{ 0, 0 }
+};
+
+/* The set of possible program key events */
+static struct sonypi_event sonypi_pkeyev[] = {
+	{ 0x01, SONYPI_EVENT_PKEY_P1 },
+	{ 0x02, SONYPI_EVENT_PKEY_P2 },
+	{ 0x04, SONYPI_EVENT_PKEY_P3 },
+	{ 0x5c, SONYPI_EVENT_PKEY_P1 },
+	{ 0, 0 }
+};
+
+/* The set of possible bluetooth events */
+static struct sonypi_event sonypi_blueev[] = {
+	{ 0x55, SONYPI_EVENT_BLUETOOTH_PRESSED },
+	{ 0x59, SONYPI_EVENT_BLUETOOTH_ON },
+	{ 0x5a, SONYPI_EVENT_BLUETOOTH_OFF },
+	{ 0, 0 }
+};
+
+/* The set of possible wireless events */
+static struct sonypi_event sonypi_wlessev[] = {
+	{ 0x59, SONYPI_EVENT_WIRELESS_ON },
+	{ 0x5a, SONYPI_EVENT_WIRELESS_OFF },
+	{ 0, 0 }
+};
+
+/* The set of possible back button events */
+static struct sonypi_event sonypi_backev[] = {
+	{ 0x20, SONYPI_EVENT_BACK_PRESSED },
+	{ 0, 0 }
+};
+
+/* The set of possible help button events */
+static struct sonypi_event sonypi_helpev[] = {
+	{ 0x3b, SONYPI_EVENT_HELP_PRESSED },
+	{ 0, 0 }
+};
+
+
+/* The set of possible lid events */
+static struct sonypi_event sonypi_lidev[] = {
+	{ 0x51, SONYPI_EVENT_LID_CLOSED },
+	{ 0x50, SONYPI_EVENT_LID_OPENED },
+	{ 0, 0 }
+};
+
+/* The set of possible zoom events */
+static struct sonypi_event sonypi_zoomev[] = {
+	{ 0x39, SONYPI_EVENT_ZOOM_PRESSED },
+	{ 0, 0 }
+};
+
+/* The set of possible thumbphrase events */
+static struct sonypi_event sonypi_thumbphraseev[] = {
+	{ 0x3a, SONYPI_EVENT_THUMBPHRASE_PRESSED },
+	{ 0, 0 }
+};
+
+/* The set of possible motioneye camera events */
+static struct sonypi_event sonypi_meyeev[] = {
+	{ 0x00, SONYPI_EVENT_MEYE_FACE },
+	{ 0x01, SONYPI_EVENT_MEYE_OPPOSITE },
+	{ 0, 0 }
+};
+
+/* The set of possible memorystick events */
+static struct sonypi_event sonypi_memorystickev[] = {
+	{ 0x53, SONYPI_EVENT_MEMORYSTICK_INSERT },
+	{ 0x54, SONYPI_EVENT_MEMORYSTICK_EJECT },
+	{ 0, 0 }
+};
+
+/* The set of possible battery events */
+static struct sonypi_event sonypi_batteryev[] = {
+	{ 0x20, SONYPI_EVENT_BATTERY_INSERT },
+	{ 0x30, SONYPI_EVENT_BATTERY_REMOVE },
+	{ 0, 0 }
+};
+
+static struct sonypi_eventtypes {
+	int			model;
+	u8			data;
+	unsigned long		mask;
+	struct sonypi_event *	events;
+} sony_pic_eventtypes[] = {
+	{ SONYPI_DEVICE_TYPE1, 0, 0xffffffff, sonypi_releaseev },
+	{ SONYPI_DEVICE_TYPE1, 0x70, SONYPI_MEYE_MASK, sonypi_meyeev },
+	{ SONYPI_DEVICE_TYPE1, 0x30, SONYPI_LID_MASK, sonypi_lidev },
+	{ SONYPI_DEVICE_TYPE1, 0x60, SONYPI_CAPTURE_MASK, sonypi_captureev },
+	{ SONYPI_DEVICE_TYPE1, 0x10, SONYPI_JOGGER_MASK, sonypi_joggerev },
+	{ SONYPI_DEVICE_TYPE1, 0x20, SONYPI_FNKEY_MASK, sonypi_fnkeyev },
+	{ SONYPI_DEVICE_TYPE1, 0x30, SONYPI_BLUETOOTH_MASK, sonypi_blueev },
+	{ SONYPI_DEVICE_TYPE1, 0x40, SONYPI_PKEY_MASK, sonypi_pkeyev },
+	{ SONYPI_DEVICE_TYPE1, 0x30, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev },
+	{ SONYPI_DEVICE_TYPE1, 0x40, SONYPI_BATTERY_MASK, sonypi_batteryev },
+
+	{ SONYPI_DEVICE_TYPE2, 0, 0xffffffff, sonypi_releaseev },
+	{ SONYPI_DEVICE_TYPE2, 0x38, SONYPI_LID_MASK, sonypi_lidev },
+	{ SONYPI_DEVICE_TYPE2, 0x11, SONYPI_JOGGER_MASK, sonypi_joggerev },
+	{ SONYPI_DEVICE_TYPE2, 0x61, SONYPI_CAPTURE_MASK, sonypi_captureev },
+	{ SONYPI_DEVICE_TYPE2, 0x21, SONYPI_FNKEY_MASK, sonypi_fnkeyev },
+	{ SONYPI_DEVICE_TYPE2, 0x31, SONYPI_BLUETOOTH_MASK, sonypi_blueev },
+	{ SONYPI_DEVICE_TYPE2, 0x08, SONYPI_PKEY_MASK, sonypi_pkeyev },
+	{ SONYPI_DEVICE_TYPE2, 0x11, SONYPI_BACK_MASK, sonypi_backev },
+	{ SONYPI_DEVICE_TYPE2, 0x21, SONYPI_HELP_MASK, sonypi_helpev },
+	{ SONYPI_DEVICE_TYPE2, 0x21, SONYPI_ZOOM_MASK, sonypi_zoomev },
+	{ SONYPI_DEVICE_TYPE2, 0x20, SONYPI_THUMBPHRASE_MASK, sonypi_thumbphraseev },
+	{ SONYPI_DEVICE_TYPE2, 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev },
+	{ SONYPI_DEVICE_TYPE2, 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev },
+	{ SONYPI_DEVICE_TYPE2, 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev },
+
+	{ SONYPI_DEVICE_TYPE3, 0, 0xffffffff, sonypi_releaseev },
+	{ SONYPI_DEVICE_TYPE3, 0x21, SONYPI_FNKEY_MASK, sonypi_fnkeyev },
+	{ SONYPI_DEVICE_TYPE3, 0x31, SONYPI_WIRELESS_MASK, sonypi_wlessev },
+	{ SONYPI_DEVICE_TYPE3, 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev },
+	{ SONYPI_DEVICE_TYPE3, 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev },
+	{ SONYPI_DEVICE_TYPE3, 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev },
+	{ 0 }
+};
+
+static int sony_pic_detect_device_type(void)
+{
+	struct pci_dev *pcidev;
+	int model = 0;
+
+	if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
+				     PCI_DEVICE_ID_INTEL_82371AB_3, NULL)))
+		model = SONYPI_DEVICE_TYPE1;
+
+	else if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
+					  PCI_DEVICE_ID_INTEL_ICH6_1, NULL)))
+		model = SONYPI_DEVICE_TYPE3;
+
+	else if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
+					  PCI_DEVICE_ID_INTEL_ICH7_1, NULL)))
+		model = SONYPI_DEVICE_TYPE3;
+
+	else
+		model = SONYPI_DEVICE_TYPE2;
+
+	if (pcidev)
+		pci_dev_put(pcidev);
+
+	printk(KERN_INFO DRV_PFX "detected Type%d model\n",
+			model == SONYPI_DEVICE_TYPE1 ? 1 :
+			model == SONYPI_DEVICE_TYPE2 ? 2 : 3);
+	return model;
+}
+
+#define ITERATIONS_LONG		10000
+#define ITERATIONS_SHORT	10
+#define wait_on_command(command, iterations) {				\
+	unsigned int n = iterations;					\
+	while (--n && (command))					\
+		udelay(1);						\
+	if (!n)								\
+		dprintk("command failed at %s : %s (line %d)\n",	\
+				__FILE__, __FUNCTION__, __LINE__);	\
+}
+
+static u8 sony_pic_call1(u8 dev)
+{
+	u8 v1, v2;
+
+	wait_on_command(inb_p(spic_dev.cur_ioport->io.minimum + 4) & 2,
+			ITERATIONS_LONG);
+	outb(dev, spic_dev.cur_ioport->io.minimum + 4);
+	v1 = inb_p(spic_dev.cur_ioport->io.minimum + 4);
+	v2 = inb_p(spic_dev.cur_ioport->io.minimum);
+	dprintk("sony_pic_call1: 0x%.4x\n", (v2 << 8) | v1);
+	return v2;
+}
+
+static u8 sony_pic_call2(u8 dev, u8 fn)
+{
+	u8 v1;
+
+	wait_on_command(inb_p(spic_dev.cur_ioport->io.minimum + 4) & 2,
+			ITERATIONS_LONG);
+	outb(dev, spic_dev.cur_ioport->io.minimum + 4);
+	wait_on_command(inb_p(spic_dev.cur_ioport->io.minimum + 4) & 2,
+			ITERATIONS_LONG);
+	outb(fn, spic_dev.cur_ioport->io.minimum);
+	v1 = inb_p(spic_dev.cur_ioport->io.minimum);
+	dprintk("sony_pic_call2: 0x%.4x\n", v1);
+	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)
+{
+	u32 i;
+	struct sony_pic_dev *dev = (struct sony_pic_dev *)context;
+
+	switch (resource->type) {
+	case ACPI_RESOURCE_TYPE_START_DEPENDENT:
+	case ACPI_RESOURCE_TYPE_END_DEPENDENT:
+		return AE_OK;
+
+	case ACPI_RESOURCE_TYPE_IRQ:
+		{
+			struct acpi_resource_irq *p = &resource->data.irq;
+			struct sony_pic_irq *interrupt = NULL;
+			if (!p || !p->interrupt_count) {
+				/*
+				 * IRQ descriptors may have no IRQ# bits set,
+				 * particularly those those w/ _STA disabled
+				 */
+				dprintk("Blank IRQ resource\n");
+				return AE_OK;
+			}
+			for (i = 0; i < p->interrupt_count; i++) {
+				if (!p->interrupts[i]) {
+					printk(KERN_WARNING DRV_PFX
+							"Invalid IRQ %d\n",
+							p->interrupts[i]);
+					continue;
+				}
+				interrupt = kzalloc(sizeof(*interrupt),
+						GFP_KERNEL);
+				if (!interrupt)
+					return AE_ERROR;
+
+				list_add(&interrupt->list, &dev->interrupts);
+				interrupt->irq.triggering = p->triggering;
+				interrupt->irq.polarity = p->polarity;
+				interrupt->irq.sharable = p->sharable;
+				interrupt->irq.interrupt_count = 1;
+				interrupt->irq.interrupts[0] = p->interrupts[i];
+			}
+			return AE_OK;
+		}
+	case ACPI_RESOURCE_TYPE_IO:
+		{
+			struct acpi_resource_io *io = &resource->data.io;
+			struct sony_pic_ioport *ioport = NULL;
+			if (!io) {
+				dprintk("Blank IO resource\n");
+				return AE_OK;
+			}
+
+			ioport = kzalloc(sizeof(*ioport), GFP_KERNEL);
+			if (!ioport)
+				return AE_ERROR;
+
+			list_add(&ioport->list, &dev->ioports);
+			memcpy(&ioport->io, io, sizeof(*io));
+			return AE_OK;
+		}
+	default:
+		dprintk("Resource %d isn't an IRQ nor an IO port\n",
+				resource->type);
+
+	case ACPI_RESOURCE_TYPE_END_TAG:
+		return AE_OK;
+	}
+	return AE_CTRL_TERMINATE;
+}
+
+static int sony_pic_possible_resources(struct acpi_device *device)
+{
+	int result = 0;
+	acpi_status status = AE_OK;
+
+	if (!device)
+		return -EINVAL;
+
+	/* get device status */
+	/* see acpi_pci_link_get_current acpi_pci_link_get_possible */
+	dprintk("Evaluating _STA\n");
+	result = acpi_bus_get_status(device);
+	if (result) {
+		printk(KERN_WARNING DRV_PFX "Unable to read status\n");
+		goto end;
+	}
+
+	if (!device->status.enabled)
+		dprintk("Device disabled\n");
+	else
+		dprintk("Device enabled\n");
+
+	/*
+	 * Query and parse 'method'
+	 */
+	dprintk("Evaluating %s\n", METHOD_NAME__PRS);
+	status = acpi_walk_resources(device->handle, METHOD_NAME__PRS,
+			sony_pic_read_possible_resource, &spic_dev);
+	if (ACPI_FAILURE(status)) {
+		printk(KERN_WARNING DRV_PFX
+				"Failure evaluating %s\n",
+				METHOD_NAME__PRS);
+		result = -ENODEV;
+	}
+end:
+	return result;
+}
+
+/*
+ *  Disable the spic device by calling its _DIS method
+ */
+static int sony_pic_disable(struct acpi_device *device)
+{
+	if (ACPI_FAILURE(acpi_evaluate_object(device->handle, "_DIS", 0, NULL)))
+		return -ENXIO;
+
+	dprintk("Device disabled\n");
+	return 0;
+}
+
+
+/*
+ *  Based on drivers/acpi/pci_link.c:acpi_pci_link_set
+ *
+ *  Call _SRS to set current resources
+ */
+static int sony_pic_enable(struct acpi_device *device,
+		struct sony_pic_ioport *ioport, struct sony_pic_irq *irq)
+{
+	acpi_status status;
+	int result = 0;
+	struct {
+		struct acpi_resource io_res;
+		struct acpi_resource irq_res;
+		struct acpi_resource end;
+	} *resource;
+	struct acpi_buffer buffer = { 0, NULL };
+
+	if (!ioport || !irq)
+		return -EINVAL;
+
+	/* init acpi_buffer */
+	resource = kzalloc(sizeof(*resource) + 1, GFP_KERNEL);
+	if (!resource)
+		return -ENOMEM;
+
+	buffer.length = sizeof(*resource) + 1;
+	buffer.pointer = resource;
+
+	/* setup io resource */
+	resource->io_res.type = ACPI_RESOURCE_TYPE_IO;
+	resource->io_res.length = sizeof(struct acpi_resource);
+	memcpy(&resource->io_res.data.io, &ioport->io,
+			sizeof(struct acpi_resource_io));
+
+	/* setup irq resource */
+	resource->irq_res.type = ACPI_RESOURCE_TYPE_IRQ;
+	resource->irq_res.length = sizeof(struct acpi_resource);
+	memcpy(&resource->irq_res.data.irq, &irq->irq,
+			sizeof(struct acpi_resource_irq));
+	/* we requested a shared irq */
+	resource->irq_res.data.irq.sharable = ACPI_SHARED;
+
+	resource->end.type = ACPI_RESOURCE_TYPE_END_TAG;
+
+	/* Attempt to set the resource */
+	dprintk("Evaluating _SRS\n");
+	status = acpi_set_current_resources(device->handle, &buffer);
+
+	/* check for total failure */
+	if (ACPI_FAILURE(status)) {
+		printk(KERN_ERR DRV_PFX "Error evaluating _SRS");
+		result = -ENODEV;
+		goto end;
+	}
+
+	/* Necessary device initializations calls (from sonypi) */
+	sony_pic_call1(0x82);
+	sony_pic_call2(0x81, 0xff);
+	sony_pic_call1(compat ? 0x92 : 0x82);
+
+end:
+	kfree(resource);
+	return result;
+}
+
+/*****************
+ *
+ * ISR: some event is available
+ *
+ *****************/
+static irqreturn_t sony_pic_irq(int irq, void *dev_id)
+{
+	int i, j;
+	u32 port_val = 0;
+	u8 ev = 0;
+	u8 data_mask = 0;
+	u8 device_event = 0;
+
+	struct sony_pic_dev *dev = (struct sony_pic_dev *) dev_id;
+
+	acpi_os_read_port(dev->cur_ioport->io.minimum, &port_val,
+			dev->cur_ioport->io.address_length);
+	ev = port_val & SONY_PIC_EV_MASK;
+	data_mask = 0xff & (port_val >> (dev->cur_ioport->io.address_length - 8));
+
+	dprintk("event (0x%.8x [%.2x] [%.2x]) at port 0x%.4x\n",
+			port_val, ev, data_mask, dev->cur_ioport->io.minimum);
+
+	if (ev == 0x00 || ev == 0xff)
+		return IRQ_HANDLED;
+
+	for (i = 0; sony_pic_eventtypes[i].model; i++) {
+
+		if (spic_dev.model != sony_pic_eventtypes[i].model)
+			continue;
+
+		if ((data_mask & sony_pic_eventtypes[i].data) !=
+		    sony_pic_eventtypes[i].data)
+			continue;
+
+		if (!(mask & sony_pic_eventtypes[i].mask))
+			continue;
+
+		for (j = 0; sony_pic_eventtypes[i].events[j].event; j++) {
+			if (ev == sony_pic_eventtypes[i].events[j].data) {
+				device_event =
+					sony_pic_eventtypes[i].events[j].event;
+				goto found;
+			}
+		}
+	}
+	return IRQ_HANDLED;
+
+found:
+	sony_pic_report_input_event(device_event);
+	acpi_bus_generate_event(spic_dev.acpi_dev, 1, device_event);
+
+	return IRQ_HANDLED;
+}
+
+/*****************
+ *
+ *  ACPI driver
+ *
+ *****************/
+static int sony_pic_remove(struct acpi_device *device, int type)
+{
+	struct sony_pic_ioport *io, *tmp_io;
+	struct sony_pic_irq *irq, *tmp_irq;
+
+	if (sony_pic_disable(device)) {
+		printk(KERN_ERR DRV_PFX "Couldn't disable device.\n");
+		return -ENXIO;
+	}
+
+	free_irq(spic_dev.cur_irq->irq.interrupts[0], &spic_dev);
+	release_region(spic_dev.cur_ioport->io.minimum,
+			spic_dev.cur_ioport->io.address_length);
+
+	sony_pic_remove_input();
+
+	list_for_each_entry_safe(io, tmp_io, &spic_dev.ioports, list) {
+		list_del(&io->list);
+		kfree(io);
+	}
+	list_for_each_entry_safe(irq, tmp_irq, &spic_dev.interrupts, list) {
+		list_del(&irq->list);
+		kfree(irq);
+	}
+	spic_dev.cur_ioport = NULL;
+	spic_dev.cur_irq = NULL;
+
+	dprintk("removed.\n");
+	return 0;
+}
+
+static int sony_pic_add(struct acpi_device *device)
+{
+	int result;
+	struct sony_pic_ioport *io, *tmp_io;
+	struct sony_pic_irq *irq, *tmp_irq;
+
+	printk(KERN_INFO DRV_PFX
+		"Sony Programmable I/O Controller Driver v%s.\n",
+		SONY_LAPTOP_DRIVER_VERSION);
+
+	spic_dev.acpi_dev = device;
+	strcpy(acpi_device_class(device), "sony/hotkey");
+	spic_dev.model = sony_pic_detect_device_type();
+
+	/* read _PRS resources */
+	result = sony_pic_possible_resources(device);
+	if (result) {
+		printk(KERN_ERR DRV_PFX
+				"Unabe to read possible resources.\n");
+		goto err_free_resources;
+	}
+
+	/* setup input devices and helper fifo */
+	result = sony_pic_setup_input();
+	if (result) {
+		printk(KERN_ERR DRV_PFX
+				"Unabe to create input devices.\n");
+		goto err_free_resources;
+	}
+
+	/* request io port */
+	list_for_each_entry(io, &spic_dev.ioports, list) {
+		if (request_region(io->io.minimum, io->io.address_length,
+					"Sony Programable I/O Device")) {
+			dprintk("I/O port: 0x%.4x (0x%.4x) + 0x%.2x\n",
+					io->io.minimum, io->io.maximum,
+					io->io.address_length);
+			spic_dev.cur_ioport = io;
+			break;
+		}
+	}
+	if (!spic_dev.cur_ioport) {
+		printk(KERN_ERR DRV_PFX "Failed to request_region.\n");
+		result = -ENODEV;
+		goto err_remove_input;
+	}
+
+	/* request IRQ */
+	list_for_each_entry(irq, &spic_dev.interrupts, list) {
+		if (!request_irq(irq->irq.interrupts[0], sony_pic_irq,
+					IRQF_SHARED, "sony-laptop", &spic_dev)) {
+			dprintk("IRQ: %d - triggering: %d - "
+					"polarity: %d - shr: %d\n",
+					irq->irq.interrupts[0],
+					irq->irq.triggering,
+					irq->irq.polarity,
+					irq->irq.sharable);
+			spic_dev.cur_irq = irq;
+			break;
+		}
+	}
+	if (!spic_dev.cur_irq) {
+		printk(KERN_ERR DRV_PFX "Failed to request_irq.\n");
+		result = -ENODEV;
+		goto err_release_region;
+	}
+
+	/* set resource status _SRS */
+	result = sony_pic_enable(device, spic_dev.cur_ioport, spic_dev.cur_irq);
+	if (result) {
+		printk(KERN_ERR DRV_PFX "Couldn't enable device.\n");
+		goto err_free_irq;
+	}
+
+	return 0;
+
+err_free_irq:
+	free_irq(spic_dev.cur_irq->irq.interrupts[0], &spic_dev);
+
+err_release_region:
+	release_region(spic_dev.cur_ioport->io.minimum,
+			spic_dev.cur_ioport->io.address_length);
+
+err_remove_input:
+	sony_pic_remove_input();
+
+err_free_resources:
+	list_for_each_entry_safe(io, tmp_io, &spic_dev.ioports, list) {
+		list_del(&io->list);
+		kfree(io);
+	}
+	list_for_each_entry_safe(irq, tmp_irq, &spic_dev.interrupts, list) {
+		list_del(&irq->list);
+		kfree(irq);
+	}
+	spic_dev.cur_ioport = NULL;
+	spic_dev.cur_irq = NULL;
+
+	return result;
+}
+
+static int sony_pic_suspend(struct acpi_device *device, pm_message_t state)
+{
+	if (sony_pic_disable(device))
+		return -ENXIO;
+	return 0;
+}
+
+static int sony_pic_resume(struct acpi_device *device)
+{
+	sony_pic_enable(device, spic_dev.cur_ioport, spic_dev.cur_irq);
+	return 0;
+}
+
+static struct acpi_driver sony_pic_driver = {
+	.name = SONY_PIC_DRIVER_NAME,
+	.class = SONY_PIC_CLASS,
+	.ids = SONY_PIC_HID,
+	.owner = THIS_MODULE,
+	.ops = {
+		.add = sony_pic_add,
+		.remove = sony_pic_remove,
+		.suspend = sony_pic_suspend,
+		.resume = sony_pic_resume,
+		},
+};
+
+static struct dmi_system_id __initdata sonypi_dmi_table[] = {
+	{
+		.ident = "Sony Vaio",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "PCG-"),
+		},
+	},
+	{
+		.ident = "Sony Vaio",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "VGN-"),
+		},
+	},
+	{ }
+};
+
 static int __init sony_laptop_init(void)
 {
-	return acpi_bus_register_driver(&sony_nc_driver);
+	int result;
+
+	if (!no_spic && dmi_check_system(sonypi_dmi_table)) {
+		result = acpi_bus_register_driver(&sony_pic_driver);
+		if (result) {
+			printk(KERN_ERR DRV_PFX
+					"Unable to register SPIC driver.");
+			goto out;
+		}
+	}
+
+	result = acpi_bus_register_driver(&sony_nc_driver);
+	if (result) {
+		printk(KERN_ERR DRV_PFX "Unable to register SNC driver.");
+		goto out_unregister_pic;
+	}
+
+	return 0;
+
+out_unregister_pic:
+	if (!no_spic)
+		acpi_bus_unregister_driver(&sony_pic_driver);
+out:
+	return result;
 }
 
 static void __exit sony_laptop_exit(void)
 {
 	acpi_bus_unregister_driver(&sony_nc_driver);
+	if (!no_spic)
+		acpi_bus_unregister_driver(&sony_pic_driver);
 }
 
 module_init(sony_laptop_init);

--
-- 
mattia
:wq!
-
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [patch 5/9] Unify the input subsystem event forwarding
       [not found] <20070409081903.057292676@linux.it>
                   ` (3 preceding siblings ...)
  2007-04-09 17:26 ` [patch 4/9] Add SNY6001 device handling (sonypi reimplementation) malattia
@ 2007-04-09 17:28 ` malattia
  2007-04-09 17:28 ` [patch 6/9] additional platform attributes coming from SNY6001 malattia
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 13+ messages in thread
From: malattia @ 2007-04-09 17:28 UTC (permalink / raw)
  To: lenb; +Cc: linux-acpi, akpm, stelian

[-- Attachment #1: 0005-unify-input-subsystem-event-fwd.patch --]
[-- Type: text/plain, Size: 17966 bytes --]

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

Signed-off-by: Mattia Dongili <malattia@linux.it>
---
 drivers/misc/sony-laptop.c |  541 +++++++++++++++++++++++++++++-----------------------------
 1 file changed, 276 insertions(+), 265 deletions(-)

Index: linux-2.6/drivers/misc/sony-laptop.c
===================================================================
--- linux-2.6.orig/drivers/misc/sony-laptop.c	2007-04-05 15:33:22.785181224 +0200
+++ linux-2.6/drivers/misc/sony-laptop.c	2007-04-05 15:33:26.285380581 +0200
@@ -97,18 +97,266 @@ MODULE_PARM_DESC(no_spic,
 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 struct backlight_ops sony_backlig
 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 @@ static int sony_nc_add(struct acpi_devic
 		}
 	}
 
+	/* 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 @@ static int sony_nc_add(struct acpi_devic
 		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 @@ static int sony_nc_add(struct acpi_devic
 					    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 @@ static int sony_nc_remove(struct acpi_de
 	}
 
 	sony_pf_remove();
+	sony_laptop_remove_input();
 
 	printk(KERN_INFO SONY_NC_DRIVER_NAME " successfully removed\n");
 
@@ -626,13 +889,8 @@ static struct acpi_driver sony_nc_driver
 #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_dev {
 	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 @@ static u8 sony_pic_call2(u8 dev, u8 fn)
 	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 @@ static irqreturn_t sony_pic_irq(int irq,
 	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 @@ static int sony_pic_remove(struct acpi_d
 	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 @@ static int sony_pic_add(struct acpi_devi
 	}
 
 	/* 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 @@ err_release_region:
 			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) {

--
-- 
mattia
:wq!

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [patch 6/9] additional platform attributes coming from SNY6001
       [not found] <20070409081903.057292676@linux.it>
                   ` (4 preceding siblings ...)
  2007-04-09 17:28 ` [patch 5/9] Unify the input subsystem event forwarding malattia
@ 2007-04-09 17:28 ` malattia
  2007-04-09 17:31 ` [patch 7/9] sanitize printks malattia
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 13+ messages in thread
From: malattia @ 2007-04-09 17:28 UTC (permalink / raw)
  To: lenb; +Cc: linux-acpi, akpm, stelian

[-- Attachment #1: 0006-add-SNY6001-platform-attributes.patch --]
[-- Type: text/plain, Size: 6291 bytes --]

Register additional platform attributes coming from the SPIC (sonypi) driver.

Signed-off-by: Mattia Dongili <malattia@linux.it>
---
 drivers/misc/sony-laptop.c |  205 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 204 insertions(+), 1 deletion(-)

Index: linux-2.6/drivers/misc/sony-laptop.c
===================================================================
--- linux-2.6.orig/drivers/misc/sony-laptop.c	2007-04-05 15:33:26.285380581 +0200
+++ linux-2.6/drivers/misc/sony-laptop.c	2007-04-05 15:33:32.785751095 +0200
@@ -774,7 +774,8 @@ static int sony_nc_add(struct acpi_devic
 
 	}
 
-	if (sony_pf_add())
+	result = sony_pf_add();
+	if (result)
 		goto outbacklight;
 
 	/* create sony_pf sysfs attributes related to the SNC device */
@@ -903,6 +904,8 @@ struct sony_pic_irq {
 
 struct sony_pic_dev {
 	int			model;
+	u8			camera_power;
+	u8			bluetooth_power;
 	struct acpi_device	*acpi_dev;
 	struct sony_pic_irq	*cur_irq;
 	struct sony_pic_ioport	*cur_ioport;
@@ -1181,6 +1184,186 @@ static u8 sony_pic_call2(u8 dev, u8 fn)
 	return v1;
 }
 
+static u8 sony_pic_call3(u8 dev, u8 fn, u8 v)
+{
+	u8 v1;
+
+	wait_on_command(inb_p(spic_dev.cur_ioport->io.minimum + 4) & 2, ITERATIONS_LONG);
+	outb(dev, spic_dev.cur_ioport->io.minimum + 4);
+	wait_on_command(inb_p(spic_dev.cur_ioport->io.minimum + 4) & 2, ITERATIONS_LONG);
+	outb(fn, spic_dev.cur_ioport->io.minimum);
+	wait_on_command(inb_p(spic_dev.cur_ioport->io.minimum + 4) & 2, ITERATIONS_LONG);
+	outb(v, spic_dev.cur_ioport->io.minimum);
+	v1 = inb_p(spic_dev.cur_ioport->io.minimum);
+	dprintk("sony_pic_call3: 0x%.4x\n", v1);
+	return v1;
+}
+
+/* camera tests and poweron/poweroff */
+#define SONYPI_CAMERA_PICTURE		5
+#define SONYPI_CAMERA_MUTE_MASK		0x40
+#define SONYPI_CAMERA_CONTROL		0x10
+#define SONYPI_CAMERA_STATUS 		7
+#define SONYPI_CAMERA_STATUS_READY 	0x2
+#define SONYPI_CAMERA_STATUS_POSITION	0x4
+
+static int sony_pic_camera_ready(void)
+{
+	u8 v;
+
+	v = sony_pic_call2(0x8f, SONYPI_CAMERA_STATUS);
+	return (v != 0xff && (v & SONYPI_CAMERA_STATUS_READY));
+}
+
+static void sony_pic_camera_off(void)
+{
+	wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_PICTURE,
+				SONYPI_CAMERA_MUTE_MASK),
+			ITERATIONS_SHORT);
+
+	if (!spic_dev.camera_power)
+		return;
+
+	sony_pic_call2(0x91, 0);
+	spic_dev.camera_power = 0;
+}
+
+static void sony_pic_camera_on(void)
+{
+	int i, j;
+
+	if (spic_dev.camera_power)
+		return;
+
+	for (j = 5; j > 0; j--) {
+
+		while (sony_pic_call2(0x91, 0x1))
+			msleep(10);
+		sony_pic_call1(0x93);
+
+		for (i = 400; i > 0; i--) {
+			if (sony_pic_camera_ready())
+				break;
+			msleep(10);
+		}
+		if (i)
+			break;
+	}
+
+	if (j == 0) {
+		printk(KERN_WARNING "sonypi: failed to power on camera\n");
+		return;
+	}
+
+	wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_CONTROL,
+				0x5a),
+			ITERATIONS_SHORT);
+
+	spic_dev.camera_power = 1;
+}
+
+static ssize_t sony_pic_camerapower_store(struct device *dev,
+		struct device_attribute *attr,
+		const char *buffer, size_t count)
+{
+	unsigned long value;
+	if (count > 31)
+		return -EINVAL;
+
+	value = simple_strtoul(buffer, NULL, 10);
+	if (value)
+		sony_pic_camera_on();
+	else
+		sony_pic_camera_off();
+
+	return count;
+}
+
+static ssize_t sony_pic_camerapower_show(struct device *dev,
+		struct device_attribute *attr, char *buffer)
+{
+	return snprintf(buffer, PAGE_SIZE, "%d\n", spic_dev.camera_power);
+}
+
+/* bluetooth subsystem power state */
+static void sony_pic_set_bluetoothpower(u8 state)
+{
+	state = !!state;
+	if (spic_dev.bluetooth_power == state)
+		return;
+	sony_pic_call2(0x96, state);
+	sony_pic_call1(0x82);
+	spic_dev.bluetooth_power = state;
+}
+
+static ssize_t sony_pic_bluetoothpower_store(struct device *dev,
+		struct device_attribute *attr,
+		const char *buffer, size_t count)
+{
+	unsigned long value;
+	if (count > 31)
+		return -EINVAL;
+
+	value = simple_strtoul(buffer, NULL, 10);
+	sony_pic_set_bluetoothpower(value);
+
+	return count;
+}
+
+static ssize_t sony_pic_bluetoothpower_show(struct device *dev,
+		struct device_attribute *attr, char *buffer)
+{
+	return snprintf(buffer, PAGE_SIZE, "%d\n", spic_dev.bluetooth_power);
+}
+
+/* fan speed */
+/* FAN0 information (reverse engineered from ACPI tables) */
+#define SONY_PIC_FAN0_STATUS	0x93
+static ssize_t sony_pic_fanspeed_store(struct device *dev,
+		struct device_attribute *attr,
+		const char *buffer, size_t count)
+{
+	unsigned long value;
+	if (count > 31)
+		return -EINVAL;
+
+	value = simple_strtoul(buffer, NULL, 10);
+	if (ec_write(SONY_PIC_FAN0_STATUS, value))
+		return -EIO;
+
+	return count;
+}
+
+static ssize_t sony_pic_fanspeed_show(struct device *dev,
+		struct device_attribute *attr, char *buffer)
+{
+	u8 value = 0;
+	if (ec_read(SONY_PIC_FAN0_STATUS, &value))
+		return -EIO;
+
+	return snprintf(buffer, PAGE_SIZE, "%d\n", value);
+}
+
+#define SPIC_ATTR(_name, _mode)					\
+struct device_attribute spic_attr_##_name = __ATTR(_name,	\
+		_mode, sony_pic_## _name ##_show,		\
+		sony_pic_## _name ##_store)
+
+static SPIC_ATTR(camerapower, 0644);
+static SPIC_ATTR(bluetoothpower, 0644);
+static SPIC_ATTR(fanspeed, 0644);
+
+static struct attribute *spic_attributes[] = {
+	&spic_attr_camerapower.attr,
+	&spic_attr_bluetoothpower.attr,
+	&spic_attr_fanspeed.attr,
+	NULL
+};
+
+static struct attribute_group spic_attribute_group = {
+	.attrs = spic_attributes
+};
+
 /*
  * ACPI callbacks
  */
@@ -1447,6 +1630,10 @@ static int sony_pic_remove(struct acpi_d
 
 	sony_laptop_remove_input();
 
+	/* pf attrs */
+	sysfs_remove_group(&sony_pf_device->dev.kobj, &spic_attribute_group);
+	sony_pf_remove();
+
 	list_for_each_entry_safe(io, tmp_io, &spic_dev.ioports, list) {
 		list_del(&io->list);
 		kfree(io);
@@ -1536,8 +1723,24 @@ static int sony_pic_add(struct acpi_devi
 		goto err_free_irq;
 	}
 
+	spic_dev.bluetooth_power = -1;
+	/* create device attributes */
+	result = sony_pf_add();
+	if (result)
+		goto err_disable_device;
+
+	result = sysfs_create_group(&sony_pf_device->dev.kobj, &spic_attribute_group);
+	if (result)
+		goto err_remove_pf;
+
 	return 0;
 
+err_remove_pf:
+	sony_pf_remove();
+
+err_disable_device:
+	sony_pic_disable(device);
+
 err_free_irq:
 	free_irq(spic_dev.cur_irq->irq.interrupts[0], &spic_dev);
 

--
-- 
mattia
:wq!

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [patch 7/9] sanitize printks
       [not found] <20070409081903.057292676@linux.it>
                   ` (5 preceding siblings ...)
  2007-04-09 17:28 ` [patch 6/9] additional platform attributes coming from SNY6001 malattia
@ 2007-04-09 17:31 ` malattia
  2007-04-09 17:31 ` [patch 8/9] update documentation and Kconfig help malattia
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 13+ messages in thread
From: malattia @ 2007-04-09 17:31 UTC (permalink / raw)
  To: lenb; +Cc: linux-acpi, akpm, stelian

[-- Attachment #1: 0007-sanitize-printk-logs.patch --]
[-- Type: text/plain, Size: 5582 bytes --]

Unify printks to resemble a unique driver.

Signed-off-by: Mattia Dongili <malattia@linux.it>
---
 drivers/misc/sony-laptop.c |   40 +++++++++++++++++++---------------------
 1 file changed, 19 insertions(+), 21 deletions(-)

Index: linux-2.6/drivers/misc/sony-laptop.c
===================================================================
--- linux-2.6.orig/drivers/misc/sony-laptop.c	2007-04-05 15:33:32.785751095 +0200
+++ linux-2.6/drivers/misc/sony-laptop.c	2007-04-05 15:33:37.786035924 +0200
@@ -64,20 +64,19 @@
 #include <linux/sonypi.h>
 
 #define DRV_PFX			"sony-laptop: "
-#define LOG_PFX			KERN_WARNING DRV_PFX
 #define dprintk(msg...)		do {			\
-	if (debug) printk(LOG_PFX  msg);		\
+	if (debug) printk(KERN_WARNING DRV_PFX  msg);	\
 } while (0)
 
 #define SONY_LAPTOP_DRIVER_VERSION	"0.5"
 
 #define SONY_NC_CLASS		"sony-nc"
 #define SONY_NC_HID		"SNY5001"
-#define SONY_NC_DRIVER_NAME	"Sony Notebook Control"
+#define SONY_NC_DRIVER_NAME	"Sony Notebook Control Driver"
 
 #define SONY_PIC_CLASS		"sony-pic"
 #define SONY_PIC_HID		"SNY6001"
-#define SONY_PIC_DRIVER_NAME	"Sony Programmable IO Control"
+#define SONY_PIC_DRIVER_NAME	"Sony Programmable IO Control Driver"
 
 MODULE_AUTHOR("Stelian Pop, Mattia Dongili");
 MODULE_DESCRIPTION("Sony laptop extras driver (SPIC and SNC ACPI device)");
@@ -518,7 +517,7 @@ static int acpi_callgetfunc(acpi_handle 
 		return 0;
 	}
 
-	printk(LOG_PFX "acpi_callreadfunc failed\n");
+	printk(KERN_WARNING DRV_PFX "acpi_callreadfunc failed\n");
 
 	return -1;
 }
@@ -544,7 +543,7 @@ static int acpi_callsetfunc(acpi_handle 
 	if (status == AE_OK) {
 		if (result != NULL) {
 			if (out_obj.type != ACPI_TYPE_INTEGER) {
-				printk(LOG_PFX "acpi_evaluate_object bad "
+				printk(KERN_WARNING DRV_PFX "acpi_evaluate_object bad "
 				       "return type\n");
 				return -1;
 			}
@@ -553,7 +552,7 @@ static int acpi_callsetfunc(acpi_handle 
 		return 0;
 	}
 
-	printk(LOG_PFX "acpi_evaluate_object failed\n");
+	printk(KERN_WARNING DRV_PFX "acpi_evaluate_object failed\n");
 
 	return -1;
 }
@@ -689,7 +688,7 @@ static acpi_status sony_walk_callback(ac
 	node = (struct acpi_namespace_node *)handle;
 	operand = (union acpi_operand_object *)node->object;
 
-	printk(LOG_PFX "method: name: %4.4s, args %X\n", node->name.ascii,
+	printk(KERN_WARNING DRV_PFX "method: name: %4.4s, args %X\n", node->name.ascii,
 	       (u32) operand->method.param_count);
 
 	return AE_OK;
@@ -724,6 +723,9 @@ static int sony_nc_add(struct acpi_devic
 	acpi_handle handle;
 	struct sony_nc_value *item;
 
+	printk(KERN_INFO DRV_PFX "%s v%s.\n",
+		SONY_NC_DRIVER_NAME, SONY_LAPTOP_DRIVER_VERSION);
+
 	sony_nc_acpi_device = device;
 	strcpy(acpi_device_class(device), "sony/hotkey");
 
@@ -733,7 +735,7 @@ static int sony_nc_add(struct acpi_devic
 		status = acpi_walk_namespace(ACPI_TYPE_METHOD, sony_nc_acpi_handle,
 					     1, sony_walk_callback, NULL, NULL);
 		if (ACPI_FAILURE(status)) {
-			printk(LOG_PFX "unable to walk acpi resources\n");
+			printk(KERN_WARNING DRV_PFX "unable to walk acpi resources\n");
 			result = -ENODEV;
 			goto outwalk;
 		}
@@ -751,7 +753,7 @@ static int sony_nc_add(struct acpi_devic
 					     ACPI_DEVICE_NOTIFY,
 					     sony_acpi_notify, NULL);
 	if (ACPI_FAILURE(status)) {
-		printk(LOG_PFX "unable to install notify handler\n");
+		printk(KERN_WARNING DRV_PFX "unable to install notify handler\n");
 		result = -ENODEV;
 		goto outinput;
 	}
@@ -762,7 +764,7 @@ static int sony_nc_add(struct acpi_devic
 								  &sony_backlight_ops);
 
 		if (IS_ERR(sony_backlight_device)) {
-			printk(LOG_PFX "unable to register backlight device\n");
+			printk(KERN_WARNING DRV_PFX "unable to register backlight device\n");
 			sony_backlight_device = NULL;
 		} else {
 			sony_backlight_device->props.brightness =
@@ -817,8 +819,6 @@ static int sony_nc_add(struct acpi_devic
 		}
 	}
 
-	printk(KERN_INFO SONY_NC_DRIVER_NAME " successfully installed\n");
-
 	return 0;
 
       out_sysfs:
@@ -835,7 +835,7 @@ static int sony_nc_add(struct acpi_devic
 					    ACPI_DEVICE_NOTIFY,
 					    sony_acpi_notify);
 	if (ACPI_FAILURE(status))
-		printk(LOG_PFX "unable to remove notify handler\n");
+		printk(KERN_WARNING DRV_PFX "unable to remove notify handler\n");
 
       outinput:
 	sony_laptop_remove_input();
@@ -858,7 +858,7 @@ static int sony_nc_remove(struct acpi_de
 					    ACPI_DEVICE_NOTIFY,
 					    sony_acpi_notify);
 	if (ACPI_FAILURE(status))
-		printk(LOG_PFX "unable to remove notify handler\n");
+		printk(KERN_WARNING DRV_PFX "unable to remove notify handler\n");
 
 	for (item = sony_nc_values; item->name; ++item) {
 		device_remove_file(&sony_pf_device->dev, &item->devattr);
@@ -866,8 +866,7 @@ static int sony_nc_remove(struct acpi_de
 
 	sony_pf_remove();
 	sony_laptop_remove_input();
-
-	printk(KERN_INFO SONY_NC_DRIVER_NAME " successfully removed\n");
+	dprintk(SONY_NC_DRIVER_NAME " removed.\n");
 
 	return 0;
 }
@@ -1645,7 +1644,7 @@ static int sony_pic_remove(struct acpi_d
 	spic_dev.cur_ioport = NULL;
 	spic_dev.cur_irq = NULL;
 
-	dprintk("removed.\n");
+	dprintk(SONY_PIC_DRIVER_NAME " removed.\n");
 	return 0;
 }
 
@@ -1655,9 +1654,8 @@ static int sony_pic_add(struct acpi_devi
 	struct sony_pic_ioport *io, *tmp_io;
 	struct sony_pic_irq *irq, *tmp_irq;
 
-	printk(KERN_INFO DRV_PFX
-		"Sony Programmable I/O Controller Driver v%s.\n",
-		SONY_LAPTOP_DRIVER_VERSION);
+	printk(KERN_INFO DRV_PFX "%s v%s.\n",
+		SONY_PIC_DRIVER_NAME, SONY_LAPTOP_DRIVER_VERSION);
 
 	spic_dev.acpi_dev = device;
 	strcpy(acpi_device_class(device), "sony/hotkey");

--
-- 
mattia
:wq!

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [patch 8/9] update documentation and Kconfig help
       [not found] <20070409081903.057292676@linux.it>
                   ` (6 preceding siblings ...)
  2007-04-09 17:31 ` [patch 7/9] sanitize printks malattia
@ 2007-04-09 17:31 ` malattia
  2007-04-09 17:31 ` [patch 9/9] sonypi backward compatibility code malattia
  2007-04-10 20:13 ` [patch 0/9] [RFC] sonypi ACPI reimplementation (resend 3) Len Brown
  9 siblings, 0 replies; 13+ messages in thread
From: malattia @ 2007-04-09 17:31 UTC (permalink / raw)
  To: lenb; +Cc: linux-acpi, akpm, stelian

[-- Attachment #1: 0008-update-documentation.patch --]
[-- Type: text/plain, Size: 4012 bytes --]

Signed-off-by: Mattia Dongili <malattia@linux.it>
---
 Documentation/sony-laptop.txt |   25 ++++++++++++++++++-------
 drivers/misc/Kconfig          |    9 ++++-----
 2 files changed, 22 insertions(+), 12 deletions(-)

Index: linux-2.6/Documentation/sony-laptop.txt
===================================================================
--- linux-2.6.orig/Documentation/sony-laptop.txt	2007-04-05 15:36:40.796465033 +0200
+++ linux-2.6/Documentation/sony-laptop.txt	2007-04-05 16:05:11.893975027 +0200
@@ -3,12 +3,18 @@ Sony Notebook Control Driver (SNC) Readm
 	Copyright (C) 2004- 2005 Stelian Pop <stelian@popies.net>
 	Copyright (C) 2007 Mattia Dongili <malattia@linux.it>
 
-This mini-driver drives the SNC device present in the ACPI BIOS of
-the Sony Vaio laptops.
+This mini-driver drives the SNC and SPIC device present in the ACPI BIOS of the
+Sony Vaio laptops. This driver mixes both devices functions under the same
+(hopefully consistent) interface. This also means that the sonypi driver is
+obsoleted by sony-laptop now.
 
-It gives access to some extra laptop functionalities. In its current
-form, this driver let the user set or query the screen brightness
-through the backlight subsystem and remove/apply power to some devices.
+Fn keys (hotkeys):
+------------------
+Some models report hotkeys through the SNC or SPIC devices, such events are
+reported both through the ACPI subsystem as acpi events and through the INPUT
+subsystem. See the logs of acpid or /proc/acpi/event and
+/proc/bus/input/devices to find out what those events are and which input
+devices are created by the driver.
 
 Backlight control:
 ------------------
@@ -39,6 +45,8 @@ The files are:
 	audiopower		power on/off the internal sound card
 	lanpower		power on/off the internal ethernet card
 				(only in debug mode)
+	bluetoothpower		power on/off the internal bluetooth device
+	fanspeed		get/set the fan speed
 
 Note that some files may be missing if they are not supported
 by your particular laptop model.
@@ -76,9 +84,9 @@ The sony-laptop driver creates, for some
 current ones found on several Vaio models), an entry under
 /sys/devices/platform/sony-laptop, just like the 'cdpower' one.
 You can create other entries corresponding to your own laptop methods by
-further editing the source (see the 'sony_acpi_values' table, and add a new
+further editing the source (see the 'sony_nc_values' table, and add a new
 entry to this table with your get/set method names using the
-HANDLE_NAMES macro).
+SNC_HANDLE_NAMES macro).
 
 Your mission, should you accept it, is to try finding out what
 those entries are for, by reading/writing random values from/to those
@@ -87,6 +95,9 @@ files and find out what is the impact on
 Should you find anything interesting, please report it back to me,
 I will not disavow all knowledge of your actions :)
 
+See also http://www.linux.it/~malattia/wiki/index.php/Sony_drivers for other
+useful info.
+
 Bugs/Limitations:
 -----------------
 
Index: linux-2.6/drivers/misc/Kconfig
===================================================================
--- linux-2.6.orig/drivers/misc/Kconfig	2007-04-05 16:47:10.537504245 +0200
+++ linux-2.6/drivers/misc/Kconfig	2007-04-05 16:51:05.550897049 +0200
@@ -112,12 +112,11 @@ config SONY_LAPTOP
 	depends on X86 && ACPI
 	select BACKLIGHT_CLASS_DEVICE
 	  ---help---
-	  This mini-driver drives the SNC device present in the ACPI BIOS of
-	  the Sony Vaio laptops.
+	  This mini-driver drives the SNC and SPIC devices present in the ACPI
+	  BIOS of the Sony Vaio laptops.
 
-	  It gives access to some extra laptop functionalities. In its current
-	  form, this driver let the user set or query the screen brightness
-	  through the backlight subsystem and remove/apply power to some
+	  It gives access to some extra laptop functionalities like Bluetooth,
+	  screen brightness control, Fn keys and allows powering on/off some
 	  devices.
 
 	  Read <file:Documentation/sony-laptop.txt> for more information.

--
-- 
mattia
:wq!

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [patch 9/9] sonypi backward compatibility code
       [not found] <20070409081903.057292676@linux.it>
                   ` (7 preceding siblings ...)
  2007-04-09 17:31 ` [patch 8/9] update documentation and Kconfig help malattia
@ 2007-04-09 17:31 ` malattia
  2007-04-10 20:13 ` [patch 0/9] [RFC] sonypi ACPI reimplementation (resend 3) Len Brown
  9 siblings, 0 replies; 13+ messages in thread
From: malattia @ 2007-04-09 17:31 UTC (permalink / raw)
  To: lenb; +Cc: linux-acpi, akpm, stelian

[-- Attachment #1: 0009-add-sonypi-compat-code.patch --]
[-- Type: text/plain, Size: 11396 bytes --]

Compatibility code to allow old sonypi bound userspace apps to still work.

Signed-off-by: Mattia Dongili <malattia@linux.it>
---
 drivers/misc/Kconfig       |    6 
 drivers/misc/sony-laptop.c |  332 ++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 335 insertions(+), 3 deletions(-)

Index: linux-acpi-2.6/drivers/misc/sony-laptop.c
===================================================================
--- linux-acpi-2.6.orig/drivers/misc/sony-laptop.c	2007-04-07 16:34:30.196444498 +0200
+++ linux-acpi-2.6/drivers/misc/sony-laptop.c	2007-04-07 16:36:16.702513832 +0200
@@ -62,6 +62,10 @@
 #include <acpi/acpi_bus.h>
 #include <asm/uaccess.h>
 #include <linux/sonypi.h>
+#ifdef CONFIG_SONY_LAPTOP_OLD
+#include <linux/poll.h>
+#include <linux/miscdevice.h>
+#endif
 
 #define DRV_PFX			"sony-laptop: "
 #define dprintk(msg...)		do {			\
@@ -96,13 +100,21 @@ MODULE_PARM_DESC(no_spic,
 static int compat;		/* = 0 */
 module_param(compat, int, 0444);
 MODULE_PARM_DESC(compat,
-		 "set this if you want to enable backward compatibility mode for SPIC");
+		 "set this if you want to enable backward compatibility mode");
 
 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)");
 
+#ifdef CONFIG_SONY_LAPTOP_OLD
+static int minor = -1;
+module_param(minor, int, 0);
+MODULE_PARM_DESC(minor,
+		 "minor number of the misc device for the SPIC compatibility code, "
+		 "default is -1 (automatic)");
+#endif
+
 /*********** Input Devices ***********/
 
 #define SONY_LAPTOP_BUF_SIZE	128
@@ -1318,6 +1330,16 @@ static ssize_t sony_pic_bluetoothpower_s
 /* fan speed */
 /* FAN0 information (reverse engineered from ACPI tables) */
 #define SONY_PIC_FAN0_STATUS	0x93
+static int sony_pic_set_fanspeed(unsigned long value)
+{
+	return ec_write(SONY_PIC_FAN0_STATUS, value);
+}
+
+static int sony_pic_get_fanspeed(u8 *value)
+{
+	return ec_read(SONY_PIC_FAN0_STATUS, value);
+}
+
 static ssize_t sony_pic_fanspeed_store(struct device *dev,
 		struct device_attribute *attr,
 		const char *buffer, size_t count)
@@ -1327,7 +1349,7 @@ static ssize_t sony_pic_fanspeed_store(s
 		return -EINVAL;
 
 	value = simple_strtoul(buffer, NULL, 10);
-	if (ec_write(SONY_PIC_FAN0_STATUS, value))
+	if (sony_pic_set_fanspeed(value))
 		return -EIO;
 
 	return count;
@@ -1337,7 +1359,7 @@ static ssize_t sony_pic_fanspeed_show(st
 		struct device_attribute *attr, char *buffer)
 {
 	u8 value = 0;
-	if (ec_read(SONY_PIC_FAN0_STATUS, &value))
+	if (sony_pic_get_fanspeed(&value))
 		return -EIO;
 
 	return snprintf(buffer, PAGE_SIZE, "%d\n", value);
@@ -1363,6 +1385,304 @@ static struct attribute_group spic_attri
 	.attrs = spic_attributes
 };
 
+/******** SONYPI compatibility **********/
+#ifdef CONFIG_SONY_LAPTOP_OLD
+
+/* battery / brightness / temperature  addresses */
+#define SONYPI_BAT_FLAGS	0x81
+#define SONYPI_LCD_LIGHT	0x96
+#define SONYPI_BAT1_PCTRM	0xa0
+#define SONYPI_BAT1_LEFT	0xa2
+#define SONYPI_BAT1_MAXRT	0xa4
+#define SONYPI_BAT2_PCTRM	0xa8
+#define SONYPI_BAT2_LEFT	0xaa
+#define SONYPI_BAT2_MAXRT	0xac
+#define SONYPI_BAT1_MAXTK	0xb0
+#define SONYPI_BAT1_FULL	0xb2
+#define SONYPI_BAT2_MAXTK	0xb8
+#define SONYPI_BAT2_FULL	0xba
+#define SONYPI_TEMP_STATUS	0xC1
+
+struct sonypi_compat_s {
+	struct fasync_struct	*fifo_async;
+	struct kfifo		*fifo;
+	spinlock_t		fifo_lock;
+	wait_queue_head_t	fifo_proc_list;
+	atomic_t		open_count;
+};
+static struct sonypi_compat_s sonypi_compat = {
+	.open_count = ATOMIC_INIT(0),
+};
+
+static int sonypi_misc_fasync(int fd, struct file *filp, int on)
+{
+	int retval;
+
+	retval = fasync_helper(fd, filp, on, &sonypi_compat.fifo_async);
+	if (retval < 0)
+		return retval;
+	return 0;
+}
+
+static int sonypi_misc_release(struct inode *inode, struct file *file)
+{
+	sonypi_misc_fasync(-1, file, 0);
+	atomic_dec(&sonypi_compat.open_count);
+	return 0;
+}
+
+static int sonypi_misc_open(struct inode *inode, struct file *file)
+{
+	/* Flush input queue on first open */
+	if (atomic_inc_return(&sonypi_compat.open_count) == 1)
+		kfifo_reset(sonypi_compat.fifo);
+	return 0;
+}
+
+static ssize_t sonypi_misc_read(struct file *file, char __user *buf,
+				size_t count, loff_t *pos)
+{
+	ssize_t ret;
+	unsigned char c;
+
+	if ((kfifo_len(sonypi_compat.fifo) == 0) &&
+	    (file->f_flags & O_NONBLOCK))
+		return -EAGAIN;
+
+	ret = wait_event_interruptible(sonypi_compat.fifo_proc_list,
+				       kfifo_len(sonypi_compat.fifo) != 0);
+	if (ret)
+		return ret;
+
+	while (ret < count &&
+	       (kfifo_get(sonypi_compat.fifo, &c, sizeof(c)) == sizeof(c))) {
+		if (put_user(c, buf++))
+			return -EFAULT;
+		ret++;
+	}
+
+	if (ret > 0) {
+		struct inode *inode = file->f_path.dentry->d_inode;
+		inode->i_atime = current_fs_time(inode->i_sb);
+	}
+
+	return ret;
+}
+
+static unsigned int sonypi_misc_poll(struct file *file, poll_table *wait)
+{
+	poll_wait(file, &sonypi_compat.fifo_proc_list, wait);
+	if (kfifo_len(sonypi_compat.fifo))
+		return POLLIN | POLLRDNORM;
+	return 0;
+}
+
+static int ec_read16(u8 addr, u16 *value)
+{
+	u8 val_lb, val_hb;
+	if (ec_read(addr, &val_lb))
+		return -1;
+	if (ec_read(addr + 1, &val_hb))
+		return -1;
+	*value = val_lb | (val_hb << 8);
+	return 0;
+}
+
+static int sonypi_misc_ioctl(struct inode *ip, struct file *fp,
+			     unsigned int cmd, unsigned long arg)
+{
+	int ret = 0;
+	void __user *argp = (void __user *)arg;
+	u8 val8;
+	u16 val16;
+	int value;
+
+	/*down(&sonypi_device.lock);*/
+	switch (cmd) {
+	case SONYPI_IOCGBRT:
+		if (sony_backlight_device == NULL) {
+			ret = -EIO;
+			break;
+		}
+		if (acpi_callgetfunc(sony_nc_acpi_handle, "GBRT", &value)) {
+			ret = -EIO;
+			break;
+		}
+		val8 = ((value & 0xff) - 1) << 5;
+		if (copy_to_user(argp, &val8, sizeof(val8)))
+				ret = -EFAULT;
+		break;
+	case SONYPI_IOCSBRT:
+		if (sony_backlight_device == NULL) {
+			ret = -EIO;
+			break;
+		}
+		if (copy_from_user(&val8, argp, sizeof(val8))) {
+			ret = -EFAULT;
+			break;
+		}
+		if (acpi_callsetfunc(sony_nc_acpi_handle, "SBRT",
+				(val8 >> 5) + 1, NULL)) {
+			ret = -EIO;
+			break;
+		}
+		/* sync the backlight device status */
+		sony_backlight_device->props.brightness =
+		    sony_backlight_get_brightness(sony_backlight_device);
+		break;
+	case SONYPI_IOCGBAT1CAP:
+		if (ec_read16(SONYPI_BAT1_FULL, &val16)) {
+			ret = -EIO;
+			break;
+		}
+		if (copy_to_user(argp, &val16, sizeof(val16)))
+			ret = -EFAULT;
+		break;
+	case SONYPI_IOCGBAT1REM:
+		if (ec_read16(SONYPI_BAT1_LEFT, &val16)) {
+			ret = -EIO;
+			break;
+		}
+		if (copy_to_user(argp, &val16, sizeof(val16)))
+			ret = -EFAULT;
+		break;
+	case SONYPI_IOCGBAT2CAP:
+		if (ec_read16(SONYPI_BAT2_FULL, &val16)) {
+			ret = -EIO;
+			break;
+		}
+		if (copy_to_user(argp, &val16, sizeof(val16)))
+			ret = -EFAULT;
+		break;
+	case SONYPI_IOCGBAT2REM:
+		if (ec_read16(SONYPI_BAT2_LEFT, &val16)) {
+			ret = -EIO;
+			break;
+		}
+		if (copy_to_user(argp, &val16, sizeof(val16)))
+			ret = -EFAULT;
+		break;
+	case SONYPI_IOCGBATFLAGS:
+		if (ec_read(SONYPI_BAT_FLAGS, &val8)) {
+			ret = -EIO;
+			break;
+		}
+		val8 &= 0x07;
+		if (copy_to_user(argp, &val8, sizeof(val8)))
+			ret = -EFAULT;
+		break;
+	case SONYPI_IOCGBLUE:
+		val8 = spic_dev.bluetooth_power;
+		if (copy_to_user(argp, &val8, sizeof(val8)))
+			ret = -EFAULT;
+		break;
+	case SONYPI_IOCSBLUE:
+		if (copy_from_user(&val8, argp, sizeof(val8))) {
+			ret = -EFAULT;
+			break;
+		}
+		sony_pic_set_bluetoothpower(val8);
+		break;
+	/* FAN Controls */
+	case SONYPI_IOCGFAN:
+		if (sony_pic_get_fanspeed(&val8)) {
+			ret = -EIO;
+			break;
+		}
+		if (copy_to_user(argp, &val8, sizeof(val8)))
+			ret = -EFAULT;
+		break;
+	case SONYPI_IOCSFAN:
+		if (copy_from_user(&val8, argp, sizeof(val8))) {
+			ret = -EFAULT;
+			break;
+		}
+		if (sony_pic_set_fanspeed(val8))
+			ret = -EIO;
+		break;
+	/* GET Temperature (useful under APM) */
+	case SONYPI_IOCGTEMP:
+		if (ec_read(SONYPI_TEMP_STATUS, &val8)) {
+			ret = -EIO;
+			break;
+		}
+		if (copy_to_user(argp, &val8, sizeof(val8)))
+			ret = -EFAULT;
+		break;
+	default:
+		ret = -EINVAL;
+	}
+	/*up(&sonypi_device.lock);*/
+	return ret;
+}
+
+static const struct file_operations sonypi_misc_fops = {
+	.owner		= THIS_MODULE,
+	.read		= sonypi_misc_read,
+	.poll		= sonypi_misc_poll,
+	.open		= sonypi_misc_open,
+	.release	= sonypi_misc_release,
+	.fasync		= sonypi_misc_fasync,
+	.ioctl		= sonypi_misc_ioctl,
+};
+
+static struct miscdevice sonypi_misc_device = {
+	.minor		= MISC_DYNAMIC_MINOR,
+	.name		= "sonypi",
+	.fops		= &sonypi_misc_fops,
+};
+
+static void sonypi_compat_report_event(u8 event)
+{
+	kfifo_put(sonypi_compat.fifo, (unsigned char *)&event, sizeof(event));
+	kill_fasync(&sonypi_compat.fifo_async, SIGIO, POLL_IN);
+	wake_up_interruptible(&sonypi_compat.fifo_proc_list);
+}
+
+static int sonypi_compat_init(void)
+{
+	int error;
+
+	spin_lock_init(&sonypi_compat.fifo_lock);
+	sonypi_compat.fifo = kfifo_alloc(SONY_LAPTOP_BUF_SIZE, GFP_KERNEL,
+					 &sonypi_compat.fifo_lock);
+	if (IS_ERR(sonypi_compat.fifo)) {
+		printk(KERN_ERR DRV_PFX "kfifo_alloc failed\n");
+		return PTR_ERR(sonypi_compat.fifo);
+	}
+
+	init_waitqueue_head(&sonypi_compat.fifo_proc_list);
+	/*init_MUTEX(&sonypi_device.lock);*/
+
+	if (minor != -1)
+		sonypi_misc_device.minor = minor;
+	error = misc_register(&sonypi_misc_device);
+	if (error) {
+		printk(KERN_ERR DRV_PFX "misc_register failed\n");
+		goto err_free_kfifo;
+	}
+	if (minor == -1)
+		printk(KERN_INFO "sonypi: device allocated minor is %d\n",
+		       sonypi_misc_device.minor);
+
+	return 0;
+
+err_free_kfifo:
+	kfifo_free(sonypi_compat.fifo);
+	return error;
+}
+
+static void sonypi_compat_exit(void)
+{
+	misc_deregister(&sonypi_misc_device);
+	kfifo_free(sonypi_compat.fifo);
+}
+#else
+static int sonypi_compat_init(void) { return 0; }
+static void sonypi_compat_exit(void) { }
+static void sonypi_compat_report_event(u8 event) { }
+#endif /* CONFIG_SONY_LAPTOP_OLD */
+
 /*
  * ACPI callbacks
  */
@@ -1604,6 +1924,7 @@ static irqreturn_t sony_pic_irq(int irq,
 found:
 	sony_laptop_report_input_event(device_event);
 	acpi_bus_generate_event(spic_dev.acpi_dev, 1, device_event);
+	sonypi_compat_report_event(device_event);
 
 	return IRQ_HANDLED;
 }
@@ -1618,6 +1939,8 @@ static int sony_pic_remove(struct acpi_d
 	struct sony_pic_ioport *io, *tmp_io;
 	struct sony_pic_irq *irq, *tmp_irq;
 
+	sonypi_compat_exit();
+
 	if (sony_pic_disable(device)) {
 		printk(KERN_ERR DRV_PFX "Couldn't disable device.\n");
 		return -ENXIO;
@@ -1731,6 +2054,9 @@ static int sony_pic_add(struct acpi_devi
 	if (result)
 		goto err_remove_pf;
 
+	if (sonypi_compat_init())
+		goto err_remove_pf;
+
 	return 0;
 
 err_remove_pf:
Index: linux-acpi-2.6/drivers/misc/Kconfig
===================================================================
--- linux-acpi-2.6.orig/drivers/misc/Kconfig	2007-04-07 16:34:30.196444498 +0200
+++ linux-acpi-2.6/drivers/misc/Kconfig	2007-04-07 16:36:53.704622407 +0200
@@ -121,6 +121,12 @@ config SONY_LAPTOP
 
 	  Read <file:Documentation/sony-laptop.txt> for more information.
 
+config SONY_LAPTOP_OLD
+	bool "Sonypi compatibility"
+	depends on SONY_LAPTOP
+	  ---help---
+	  Build the sonypi driver compatibility code into the sony-laptop driver.
+
 config THINKPAD_ACPI
 	tristate "ThinkPad ACPI Laptop Extras"
 	depends on X86 && ACPI

--
-- 
mattia
:wq!

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [patch 0/9] [RFC] sonypi ACPI reimplementation (resend 3)
       [not found] <20070409081903.057292676@linux.it>
                   ` (8 preceding siblings ...)
  2007-04-09 17:31 ` [patch 9/9] sonypi backward compatibility code malattia
@ 2007-04-10 20:13 ` Len Brown
  2007-04-10 22:04   ` Mattia Dongili
  9 siblings, 1 reply; 13+ messages in thread
From: Len Brown @ 2007-04-10 20:13 UTC (permalink / raw)
  To: malattia; +Cc: linux-acpi, akpm, stelian

On Monday 09 April 2007 04:19, malattia@linux.it wrote:
> [Resend 3: hopefully this time it will make to the list and the intended
> recipients]
> 
> The following patch series is the state of the art of my work toward
> reimplementing sonypi into sony-laptop. Most patches are mostly cosmetic
> to try to obtain a decent namespace separation between the used
> subsystems and the drivers driving the two sony devices (SNC and SPIC).
> If suitable it would be nice to start applying to acpi-test so that akpm
> gets them in -mm (update: it's already in .21-rc6-mm1).
> 
> Len, if you prefer a big large patch or a different series, just ask.

This is fine, thanks.

> The most interesting patches are probably 0004, 0006 and 0009.
> Andrew, the 9th patch is now really against acpi-test (I think the Kconfig hunk
> didn't apply correclty).

BTW. I check-in on top of Linus' tree, not on top of acpi-test.
Then i merge into acpi-test.  So in the future, you could just as well base
on Linus' tree and let me deal with the conflicts within acpi-test.
fine with me either way, just mention where the base is like you have.

> 0001-Remove-ACPI-references-from-variable-and-function-names.patch
> 0002-prepare-pfdriver-for-multiple-users.patch
> 0003-introduce-debug-macros.patch
> 0004-add-sny6001-device-handling-from-sonypi.patch
> 0005-unify-input-subsystem-event-fwd.patch
> 0006-add-SNY6001-platform-attributes.patch
> 0007-sanitize-printk-logs.patch
> 0008-update-documentation.patch
> 0009-add-sonypi-compat-code.patch
> ---
>  Documentation/sony-laptop.txt |   25 
>  drivers/misc/Kconfig          |   15 
>  drivers/misc/sony-laptop.c    | 2019 +++++++++++++++++++++++++++++++++++++-----
>  3 files changed, 1842 insertions(+), 217 deletions(-)


>SONY_LAPTOP_OLD 

There is probably a better name for this -- like SONY_PI_COMPATIBILITY or something.

What about CONFIG_SONYPI? -- should it now depend on this driver not being included?

SONYPI depends on !64BIT -- is that invalid, or perhaps you only need the compatibility
stuff only in 32-bit mode?

applied to acpi-test.

It would be great if you can get some test feedback for the sonypi-era features
to make sure that the code moved into the new driver works as well as the old sonypi.

thanks,
-Len

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [patch 0/9] [RFC] sonypi ACPI reimplementation (resend 3)
  2007-04-10 20:13 ` [patch 0/9] [RFC] sonypi ACPI reimplementation (resend 3) Len Brown
@ 2007-04-10 22:04   ` Mattia Dongili
  2007-04-12  9:20     ` Stelian Pop
  0 siblings, 1 reply; 13+ messages in thread
From: Mattia Dongili @ 2007-04-10 22:04 UTC (permalink / raw)
  To: Len Brown; +Cc: linux-acpi, akpm, stelian

On Tue, Apr 10, 2007 at 04:13:43PM -0400, Len Brown wrote:
> On Monday 09 April 2007 04:19, malattia@linux.it wrote:
...
> >SONY_LAPTOP_OLD 
> 
> There is probably a better name for this -- like SONY_PI_COMPATIBILITY or something.

ok, will change asap, I have a couple more patches here that I'll send
in soon.

> What about CONFIG_SONYPI? -- should it now depend on this driver not being included?

So, all in all I'd like to obsolete sonypi as soon as possible to get more feedback
but the 2 drivers can still live together for a while.

When you try to load both 2 things can happen:
- if you load sonypi first it will steal part of sony-laptop
  functionalities (the rewrite stuff for the SPIC acpi device)
- if you load sony-laptop first sonypi will bomb out with   
	kobject_add failed for sonypi with -EEXIST
  on misc_register(). sony-laptop also offers a no_spic option to not
  drive the SPIC device.

The only function that sony-laptop doesn't offer is the motion eye
camera stuff, which the meye driver also depend on and which makes
sonypi useful at least for a couple of vaio models.  I can add it to
sony-laptop[1] but I can't test.
I should probably add some printks in sonypi to suggest moving towards
sony-laptop and try to detect if the known ioports are being used by
sony-laptop to better handle the sonypi load failure (see below).

[1]: there are some bits in the patches I submitted but I'll remove them
with the next submission.

> SONYPI depends on !64BIT -- is that invalid, or perhaps you only need the compatibility
> stuff only in 32-bit mode?

it's invalid. I'd rather avoid changing sonypi to work also on 64bit,
for 64bit vaios the new sony-laptop should be good enough.

> applied to acpi-test.

Thanks!

> It would be great if you can get some test feedback for the sonypi-era features
> to make sure that the code moved into the new driver works as well as the old sonypi.

I already asked a couple of users to try it and it seems to work well
for them (and for their purposes). I guess obsoleting sonypi may
increase the reports number ;)

-- 
mattia
:wq!

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [patch 0/9] [RFC] sonypi ACPI reimplementation (resend 3)
  2007-04-10 22:04   ` Mattia Dongili
@ 2007-04-12  9:20     ` Stelian Pop
  0 siblings, 0 replies; 13+ messages in thread
From: Stelian Pop @ 2007-04-12  9:20 UTC (permalink / raw)
  To: Mattia Dongili; +Cc: Len Brown, linux-acpi, akpm

Le mercredi 11 avril 2007 à 00:04 +0200, Mattia Dongili a écrit :

> The only function that sony-laptop doesn't offer is the motion eye
> camera stuff, which the meye driver also depend on and which makes
> sonypi useful at least for a couple of vaio models.  I can add it to
> sony-laptop[1] but I can't test.

The meye stuff is quite trivial, I think you can try putting it in and
let the users test...

> I should probably add some printks in sonypi to suggest moving towards
> sony-laptop and try to detect if the known ioports are being used by
> sony-laptop to better handle the sonypi load failure (see below).

This would be a good idea. Maybe let it printk a pointer to the sonypi
wiki.

I have also put links to the new wiki on my sonypi web pages, this
should help the users find the relevant information.

-- 
Stelian Pop <stelian@popies.net>

-
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2007-04-12  9:20 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <20070409081903.057292676@linux.it>
2007-04-09 17:18 ` [patch 1/9] Remove ACPI references from variable and function names malattia
2007-04-09 17:20 ` [patch 2/9] Prepare the platform driver for multiple users malattia
2007-04-09 17:22 ` [patch 3/9] Add debug macros also used by the sonypi reimplementation malattia
2007-04-09 17:26 ` [patch 4/9] Add SNY6001 device handling (sonypi reimplementation) malattia
2007-04-09 17:28 ` [patch 5/9] Unify the input subsystem event forwarding malattia
2007-04-09 17:28 ` [patch 6/9] additional platform attributes coming from SNY6001 malattia
2007-04-09 17:31 ` [patch 7/9] sanitize printks malattia
2007-04-09 17:31 ` [patch 8/9] update documentation and Kconfig help malattia
2007-04-09 17:31 ` [patch 9/9] sonypi backward compatibility code malattia
2007-04-10 20:13 ` [patch 0/9] [RFC] sonypi ACPI reimplementation (resend 3) Len Brown
2007-04-10 22:04   ` Mattia Dongili
2007-04-12  9:20     ` Stelian Pop
2007-04-09 17:15 malattia

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox