summary refs log tree commit diff
path: root/drivers/platform/x86/asus-wmi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/platform/x86/asus-wmi.c')
-rw-r--r--drivers/platform/x86/asus-wmi.c162
1 files changed, 65 insertions, 97 deletions
diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
index 39ce3c1a7712..34e6b4d83a93 100644
--- a/drivers/platform/x86/asus-wmi.c
+++ b/drivers/platform/x86/asus-wmi.c
@@ -70,6 +70,8 @@ MODULE_LICENSE("GPL");
 #define ASUS_WMI_METHODID_DEVS		0x53564544
 #define ASUS_WMI_METHODID_CFVS		0x53564643
 
+#define ASUS_WMI_UNSUPPORTED_METHOD	0xFFFFFFFE
+
 /* Wireless */
 #define ASUS_WMI_DEVID_WLAN		0x00010011
 #define ASUS_WMI_DEVID_BLUETOOTH	0x00010013
@@ -98,9 +100,9 @@ MODULE_LICENSE("GPL");
 #define ASUS_WMI_DSTS_MAX_BRIGTH_MASK	0x0000FF00
 
 struct bios_args {
-	u32 dev_id;
-	u32 ctrl_param;
-};
+	u32 arg0;
+	u32 arg1;
+} __packed;
 
 /*
  * <platform>/    - debugfs root directory
@@ -187,20 +189,24 @@ static void asus_wmi_input_exit(struct asus_wmi *asus)
 	asus->inputdev = NULL;
 }
 
-static acpi_status asus_wmi_get_devstate(u32 dev_id, u32 *retval)
+static int asus_wmi_evaluate_method(u32 method_id, u32 arg0, u32 arg1,
+				    u32 *retval)
 {
-	struct acpi_buffer input = { (acpi_size) sizeof(u32), &dev_id };
+	struct bios_args args = {
+		.arg0 = arg0,
+		.arg1 = arg1,
+	};
+	struct acpi_buffer input = { (acpi_size) sizeof(args), &args };
 	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
-	union acpi_object *obj;
 	acpi_status status;
+	union acpi_object *obj;
 	u32 tmp;
 
-	status = wmi_evaluate_method(ASUS_WMI_MGMT_GUID,
-				     1, ASUS_WMI_METHODID_DSTS,
+	status = wmi_evaluate_method(ASUS_WMI_MGMT_GUID, 1, method_id,
 				     &input, &output);
 
 	if (ACPI_FAILURE(status))
-		return status;
+		goto exit;
 
 	obj = (union acpi_object *)output.pointer;
 	if (obj && obj->type == ACPI_TYPE_INTEGER)
@@ -213,60 +219,39 @@ static acpi_status asus_wmi_get_devstate(u32 dev_id, u32 *retval)
 
 	kfree(obj);
 
-	return status;
+exit:
+	if (ACPI_FAILURE(status))
+		return -EIO;
+
+	if (tmp == ASUS_WMI_UNSUPPORTED_METHOD)
+		return -ENODEV;
 
+	return 0;
 }
 
-static acpi_status asus_wmi_set_devstate(u32 dev_id, u32 ctrl_param,
-					 u32 *retval)
+static int asus_wmi_get_devstate(u32 dev_id, u32 *retval)
 {
-	struct bios_args args = {
-		.dev_id = dev_id,
-		.ctrl_param = ctrl_param,
-	};
-	struct acpi_buffer input = { (acpi_size) sizeof(args), &args };
-	acpi_status status;
-
-	if (!retval) {
-		status = wmi_evaluate_method(ASUS_WMI_MGMT_GUID, 1,
-					     ASUS_WMI_METHODID_DEVS,
-					     &input, NULL);
-	} else {
-		struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
-		union acpi_object *obj;
-		u32 tmp;
-
-		status = wmi_evaluate_method(ASUS_WMI_MGMT_GUID, 1,
-					     ASUS_WMI_METHODID_DEVS,
-					     &input, &output);
-
-		if (ACPI_FAILURE(status))
-			return status;
-
-		obj = (union acpi_object *)output.pointer;
-		if (obj && obj->type == ACPI_TYPE_INTEGER)
-			tmp = (u32) obj->integer.value;
-		else
-			tmp = 0;
-
-		*retval = tmp;
-
-		kfree(obj);
-	}
+	return asus_wmi_evaluate_method(ASUS_WMI_METHODID_DSTS, dev_id,
+					0, retval);
+}
 
-	return status;
+static int asus_wmi_set_devstate(u32 dev_id, u32 ctrl_param,
+					 u32 *retval)
+{
+	return asus_wmi_evaluate_method(ASUS_WMI_METHODID_DEVS, dev_id,
+					ctrl_param, retval);
 }
 
 /* Helper for special devices with magic return codes */
 static int asus_wmi_get_devstate_bits(u32 dev_id, u32 mask)
 {
 	u32 retval = 0;
-	acpi_status status;
+	int err;
 
-	status = asus_wmi_get_devstate(dev_id, &retval);
+	err = asus_wmi_get_devstate(dev_id, &retval);
 
-	if (ACPI_FAILURE(status))
-		return -EINVAL;
+	if (err < 0)
+		return err;
 
 	if (!(retval & ASUS_WMI_DSTS_PRESENCE_BIT))
 		return -ENODEV;
@@ -584,14 +569,8 @@ static int asus_rfkill_set(void *data, bool blocked)
 {
 	struct asus_rfkill *priv = data;
 	u32 ctrl_param = !blocked;
-	acpi_status status;
-
-	status = asus_wmi_set_devstate(priv->dev_id, ctrl_param, NULL);
-
-	if (ACPI_FAILURE(status))
-		return -EIO;
 
-	return 0;
+	return asus_wmi_set_devstate(priv->dev_id, ctrl_param, NULL);
 }
 
 static void asus_rfkill_query(struct rfkill *rfkill, void *data)
@@ -784,38 +763,34 @@ static int read_backlight_power(void)
 static int read_brightness(struct backlight_device *bd)
 {
 	u32 retval;
-	acpi_status status;
+	int err;
 
-	status = asus_wmi_get_devstate(ASUS_WMI_DEVID_BRIGHTNESS, &retval);
+	err = asus_wmi_get_devstate(ASUS_WMI_DEVID_BRIGHTNESS, &retval);
 
-	if (ACPI_FAILURE(status))
-		return -EIO;
-	else
-		return retval & ASUS_WMI_DSTS_BRIGHTNESS_MASK;
+	if (err < 0)
+		return err;
+
+	return retval & ASUS_WMI_DSTS_BRIGHTNESS_MASK;
 }
 
 static int update_bl_status(struct backlight_device *bd)
 {
 	u32 ctrl_param;
-	acpi_status status;
-	int power;
+	int power, err;
 
 	ctrl_param = bd->props.brightness;
 
-	status = asus_wmi_set_devstate(ASUS_WMI_DEVID_BRIGHTNESS,
-				       ctrl_param, NULL);
+	err = asus_wmi_set_devstate(ASUS_WMI_DEVID_BRIGHTNESS,
+				    ctrl_param, NULL);
 
-	if (ACPI_FAILURE(status))
-		return -EIO;
+	if (err < 0)
+		return err;
 
 	power = read_backlight_power();
 	if (power != -ENODEV && bd->props.power != power) {
 		ctrl_param = !!(bd->props.power == FB_BLANK_UNBLANK);
-		status = asus_wmi_set_devstate(ASUS_WMI_DEVID_BACKLIGHT,
-					       ctrl_param, NULL);
-
-		if (ACPI_FAILURE(status))
-			return -EIO;
+		err = asus_wmi_set_devstate(ASUS_WMI_DEVID_BACKLIGHT,
+					    ctrl_param, NULL);
 	}
 	return 0;
 }
@@ -948,19 +923,19 @@ static int parse_arg(const char *buf, unsigned long count, int *val)
 
 static ssize_t store_sys_wmi(int devid, const char *buf, size_t count)
 {
-	acpi_status status;
 	u32 retval;
-	int rv, value;
+	int rv, err, value;
 
 	value = asus_wmi_get_devstate_simple(devid);
 	if (value == -ENODEV)	/* Check device presence */
 		return value;
 
 	rv = parse_arg(buf, count, &value);
-	status = asus_wmi_set_devstate(devid, value, &retval);
+	err = asus_wmi_set_devstate(devid, value, &retval);
+
+	if (err < 0)
+		return err;
 
-	if (ACPI_FAILURE(status))
-		return -EIO;
 	return rv;
 }
 
@@ -1003,21 +978,13 @@ static ssize_t store_cpufv(struct device *dev, struct device_attribute *attr,
 			   const char *buf, size_t count)
 {
 	int value;
-	struct acpi_buffer input = { (acpi_size) sizeof(value), &value };
-	acpi_status status;
 
 	if (!count || sscanf(buf, "%i", &value) != 1)
 		return -EINVAL;
 	if (value < 0 || value > 2)
 		return -EINVAL;
 
-	status = wmi_evaluate_method(ASUS_WMI_MGMT_GUID,
-				     1, ASUS_WMI_METHODID_CFVS, &input, NULL);
-
-	if (ACPI_FAILURE(status))
-		return -EIO;
-	else
-		return count;
+	return asus_wmi_evaluate_method(ASUS_WMI_METHODID_CFVS, value, 0, NULL);
 }
 
 static DEVICE_ATTR(cpufv, S_IRUGO | S_IWUSR, NULL, store_cpufv);
@@ -1089,13 +1056,13 @@ struct asus_wmi_debugfs_node {
 static int show_dsts(struct seq_file *m, void *data)
 {
 	struct asus_wmi *asus = m->private;
-	acpi_status status;
+	int err;
 	u32 retval = -1;
 
-	status = asus_wmi_get_devstate(asus->debug.dev_id, &retval);
+	err = asus_wmi_get_devstate(asus->debug.dev_id, &retval);
 
-	if (ACPI_FAILURE(status))
-		return -EIO;
+	if (err < 0)
+		return err;
 
 	seq_printf(m, "DSTS(%x) = %x\n", asus->debug.dev_id, retval);
 
@@ -1105,13 +1072,14 @@ static int show_dsts(struct seq_file *m, void *data)
 static int show_devs(struct seq_file *m, void *data)
 {
 	struct asus_wmi *asus = m->private;
-	acpi_status status;
+	int err;
 	u32 retval = -1;
 
-	status = asus_wmi_set_devstate(asus->debug.dev_id,
-				       asus->debug.ctrl_param, &retval);
-	if (ACPI_FAILURE(status))
-		return -EIO;
+	err = asus_wmi_set_devstate(asus->debug.dev_id, asus->debug.ctrl_param,
+				    &retval);
+
+	if (err < 0)
+		return err;
 
 	seq_printf(m, "DEVS(%x, %x) = %x\n", asus->debug.dev_id,
 		   asus->debug.ctrl_param, retval);