aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform/x86
diff options
context:
space:
mode:
authorCorentin Chary <corentincj@iksaif.net>2011-02-26 04:20:35 -0500
committerMatthew Garrett <mjg@redhat.com>2011-03-28 06:07:21 -0400
commitd33da3b6866975b17fbec67540f6153f5dcdcec7 (patch)
treef679dc63b98fafe77e7561b4ed49d206cc25a380 /drivers/platform/x86
parenta75fe0d78ec00d3d5b2c42b1ee76b22e99f213d1 (diff)
asus-wmi: factorise wmi_evaluate_method call
This patch create a single function to call the WMI methods. This function handle inexistent methods (when implemented by the WMI devices, and this is not the case on Eee PCs), ACPI errors, etc.. Also pack struct bios_arg, and make sure that we always send a 64bit buffer when calling a WMI method, because this is needed on Asus notebooks. Signed-off-by: Corentin Chary <corentincj@iksaif.net> Signed-off-by: Matthew Garrett <mjg@redhat.com>
Diffstat (limited to 'drivers/platform/x86')
-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");
70#define ASUS_WMI_METHODID_DEVS 0x53564544 70#define ASUS_WMI_METHODID_DEVS 0x53564544
71#define ASUS_WMI_METHODID_CFVS 0x53564643 71#define ASUS_WMI_METHODID_CFVS 0x53564643
72 72
73#define ASUS_WMI_UNSUPPORTED_METHOD 0xFFFFFFFE
74
73/* Wireless */ 75/* Wireless */
74#define ASUS_WMI_DEVID_WLAN 0x00010011 76#define ASUS_WMI_DEVID_WLAN 0x00010011
75#define ASUS_WMI_DEVID_BLUETOOTH 0x00010013 77#define ASUS_WMI_DEVID_BLUETOOTH 0x00010013
@@ -98,9 +100,9 @@ MODULE_LICENSE("GPL");
98#define ASUS_WMI_DSTS_MAX_BRIGTH_MASK 0x0000FF00 100#define ASUS_WMI_DSTS_MAX_BRIGTH_MASK 0x0000FF00
99 101
100struct bios_args { 102struct bios_args {
101 u32 dev_id; 103 u32 arg0;
102 u32 ctrl_param; 104 u32 arg1;
103}; 105} __packed;
104 106
105/* 107/*
106 * <platform>/ - debugfs root directory 108 * <platform>/ - debugfs root directory
@@ -187,20 +189,24 @@ static void asus_wmi_input_exit(struct asus_wmi *asus)
187 asus->inputdev = NULL; 189 asus->inputdev = NULL;
188} 190}
189 191
190static acpi_status asus_wmi_get_devstate(u32 dev_id, u32 *retval) 192static int asus_wmi_evaluate_method(u32 method_id, u32 arg0, u32 arg1,
193 u32 *retval)
191{ 194{
192 struct acpi_buffer input = { (acpi_size) sizeof(u32), &dev_id }; 195 struct bios_args args = {
196 .arg0 = arg0,
197 .arg1 = arg1,
198 };
199 struct acpi_buffer input = { (acpi_size) sizeof(args), &args };
193 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; 200 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
194 union acpi_object *obj;
195 acpi_status status; 201 acpi_status status;
202 union acpi_object *obj;
196 u32 tmp; 203 u32 tmp;
197 204
198 status = wmi_evaluate_method(ASUS_WMI_MGMT_GUID, 205 status = wmi_evaluate_method(ASUS_WMI_MGMT_GUID, 1, method_id,
199 1, ASUS_WMI_METHODID_DSTS,
200 &input, &output); 206 &input, &output);
201 207
202 if (ACPI_FAILURE(status)) 208 if (ACPI_FAILURE(status))
203 return status; 209 goto exit;
204 210
205 obj = (union acpi_object *)output.pointer; 211 obj = (union acpi_object *)output.pointer;
206 if (obj && obj->type == ACPI_TYPE_INTEGER) 212 if (obj && obj->type == ACPI_TYPE_INTEGER)
@@ -213,60 +219,39 @@ static acpi_status asus_wmi_get_devstate(u32 dev_id, u32 *retval)
213 219
214 kfree(obj); 220 kfree(obj);
215 221
216 return status; 222exit:
223 if (ACPI_FAILURE(status))
224 return -EIO;
225
226 if (tmp == ASUS_WMI_UNSUPPORTED_METHOD)
227 return -ENODEV;
217 228
229 return 0;
218} 230}
219 231
220static acpi_status asus_wmi_set_devstate(u32 dev_id, u32 ctrl_param, 232static int asus_wmi_get_devstate(u32 dev_id, u32 *retval)
221 u32 *retval)
222{ 233{
223 struct bios_args args = { 234 return asus_wmi_evaluate_method(ASUS_WMI_METHODID_DSTS, dev_id,
224 .dev_id = dev_id, 235 0, retval);
225 .ctrl_param = ctrl_param, 236}
226 };
227 struct acpi_buffer input = { (acpi_size) sizeof(args), &args };
228 acpi_status status;
229
230 if (!retval) {
231 status = wmi_evaluate_method(ASUS_WMI_MGMT_GUID, 1,
232 ASUS_WMI_METHODID_DEVS,
233 &input, NULL);
234 } else {
235 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
236 union acpi_object *obj;
237 u32 tmp;
238
239 status = wmi_evaluate_method(ASUS_WMI_MGMT_GUID, 1,
240 ASUS_WMI_METHODID_DEVS,
241 &input, &output);
242
243 if (ACPI_FAILURE(status))
244 return status;
245
246 obj = (union acpi_object *)output.pointer;
247 if (obj && obj->type == ACPI_TYPE_INTEGER)
248 tmp = (u32) obj->integer.value;
249 else
250 tmp = 0;
251
252 *retval = tmp;
253
254 kfree(obj);
255 }
256 237
257 return status; 238static int asus_wmi_set_devstate(u32 dev_id, u32 ctrl_param,
239 u32 *retval)
240{
241 return asus_wmi_evaluate_method(ASUS_WMI_METHODID_DEVS, dev_id,
242 ctrl_param, retval);
258} 243}
259 244
260/* Helper for special devices with magic return codes */ 245/* Helper for special devices with magic return codes */
261static int asus_wmi_get_devstate_bits(u32 dev_id, u32 mask) 246static int asus_wmi_get_devstate_bits(u32 dev_id, u32 mask)
262{ 247{
263 u32 retval = 0; 248 u32 retval = 0;
264 acpi_status status; 249 int err;
265 250
266 status = asus_wmi_get_devstate(dev_id, &retval); 251 err = asus_wmi_get_devstate(dev_id, &retval);
267 252
268 if (ACPI_FAILURE(status)) 253 if (err < 0)
269 return -EINVAL; 254 return err;
270 255
271 if (!(retval & ASUS_WMI_DSTS_PRESENCE_BIT)) 256 if (!(retval & ASUS_WMI_DSTS_PRESENCE_BIT))
272 return -ENODEV; 257 return -ENODEV;
@@ -584,14 +569,8 @@ static int asus_rfkill_set(void *data, bool blocked)
584{ 569{
585 struct asus_rfkill *priv = data; 570 struct asus_rfkill *priv = data;
586 u32 ctrl_param = !blocked; 571 u32 ctrl_param = !blocked;
587 acpi_status status;
588
589 status = asus_wmi_set_devstate(priv->dev_id, ctrl_param, NULL);
590
591 if (ACPI_FAILURE(status))
592 return -EIO;
593 572
594 return 0; 573 return asus_wmi_set_devstate(priv->dev_id, ctrl_param, NULL);
595} 574}
596 575
597static void asus_rfkill_query(struct rfkill *rfkill, void *data) 576static void asus_rfkill_query(struct rfkill *rfkill, void *data)
@@ -784,38 +763,34 @@ static int read_backlight_power(void)
784static int read_brightness(struct backlight_device *bd) 763static int read_brightness(struct backlight_device *bd)
785{ 764{
786 u32 retval; 765 u32 retval;
787 acpi_status status; 766 int err;
788 767
789 status = asus_wmi_get_devstate(ASUS_WMI_DEVID_BRIGHTNESS, &retval); 768 err = asus_wmi_get_devstate(ASUS_WMI_DEVID_BRIGHTNESS, &retval);
790 769
791 if (ACPI_FAILURE(status)) 770 if (err < 0)
792 return -EIO; 771 return err;
793 else 772
794 return retval & ASUS_WMI_DSTS_BRIGHTNESS_MASK; 773 return retval & ASUS_WMI_DSTS_BRIGHTNESS_MASK;
795} 774}
796 775
797static int update_bl_status(struct backlight_device *bd) 776static int update_bl_status(struct backlight_device *bd)
798{ 777{
799 u32 ctrl_param; 778 u32 ctrl_param;
800 acpi_status status; 779 int power, err;
801 int power;
802 780
803 ctrl_param = bd->props.brightness; 781 ctrl_param = bd->props.brightness;
804 782
805 status = asus_wmi_set_devstate(ASUS_WMI_DEVID_BRIGHTNESS, 783 err = asus_wmi_set_devstate(ASUS_WMI_DEVID_BRIGHTNESS,
806 ctrl_param, NULL); 784 ctrl_param, NULL);
807 785
808 if (ACPI_FAILURE(status)) 786 if (err < 0)
809 return -EIO; 787 return err;
810 788
811 power = read_backlight_power(); 789 power = read_backlight_power();
812 if (power != -ENODEV && bd->props.power != power) { 790 if (power != -ENODEV && bd->props.power != power) {
813 ctrl_param = !!(bd->props.power == FB_BLANK_UNBLANK); 791 ctrl_param = !!(bd->props.power == FB_BLANK_UNBLANK);
814 status = asus_wmi_set_devstate(ASUS_WMI_DEVID_BACKLIGHT, 792 err = asus_wmi_set_devstate(ASUS_WMI_DEVID_BACKLIGHT,
815 ctrl_param, NULL); 793 ctrl_param, NULL);
816
817 if (ACPI_FAILURE(status))
818 return -EIO;
819 } 794 }
820 return 0; 795 return 0;
821} 796}
@@ -948,19 +923,19 @@ static int parse_arg(const char *buf, unsigned long count, int *val)
948 923
949static ssize_t store_sys_wmi(int devid, const char *buf, size_t count) 924static ssize_t store_sys_wmi(int devid, const char *buf, size_t count)
950{ 925{
951 acpi_status status;
952 u32 retval; 926 u32 retval;
953 int rv, value; 927 int rv, err, value;
954 928
955 value = asus_wmi_get_devstate_simple(devid); 929 value = asus_wmi_get_devstate_simple(devid);
956 if (value == -ENODEV) /* Check device presence */ 930 if (value == -ENODEV) /* Check device presence */
957 return value; 931 return value;
958 932
959 rv = parse_arg(buf, count, &value); 933 rv = parse_arg(buf, count, &value);
960 status = asus_wmi_set_devstate(devid, value, &retval); 934 err = asus_wmi_set_devstate(devid, value, &retval);
935
936 if (err < 0)
937 return err;
961 938
962 if (ACPI_FAILURE(status))
963 return -EIO;
964 return rv; 939 return rv;
965} 940}
966 941
@@ -1003,21 +978,13 @@ static ssize_t store_cpufv(struct device *dev, struct device_attribute *attr,
1003 const char *buf, size_t count) 978 const char *buf, size_t count)
1004{ 979{
1005 int value; 980 int value;
1006 struct acpi_buffer input = { (acpi_size) sizeof(value), &value };
1007 acpi_status status;
1008 981
1009 if (!count || sscanf(buf, "%i", &value) != 1) 982 if (!count || sscanf(buf, "%i", &value) != 1)
1010 return -EINVAL; 983 return -EINVAL;
1011 if (value < 0 || value > 2) 984 if (value < 0 || value > 2)
1012 return -EINVAL; 985 return -EINVAL;
1013 986
1014 status = wmi_evaluate_method(ASUS_WMI_MGMT_GUID, 987 return asus_wmi_evaluate_method(ASUS_WMI_METHODID_CFVS, value, 0, NULL);
1015 1, ASUS_WMI_METHODID_CFVS, &input, NULL);
1016
1017 if (ACPI_FAILURE(status))
1018 return -EIO;
1019 else
1020 return count;
1021} 988}
1022 989
1023static DEVICE_ATTR(cpufv, S_IRUGO | S_IWUSR, NULL, store_cpufv); 990static DEVICE_ATTR(cpufv, S_IRUGO | S_IWUSR, NULL, store_cpufv);
@@ -1089,13 +1056,13 @@ struct asus_wmi_debugfs_node {
1089static int show_dsts(struct seq_file *m, void *data) 1056static int show_dsts(struct seq_file *m, void *data)
1090{ 1057{
1091 struct asus_wmi *asus = m->private; 1058 struct asus_wmi *asus = m->private;
1092 acpi_status status; 1059 int err;
1093 u32 retval = -1; 1060 u32 retval = -1;
1094 1061
1095 status = asus_wmi_get_devstate(asus->debug.dev_id, &retval); 1062 err = asus_wmi_get_devstate(asus->debug.dev_id, &retval);
1096 1063
1097 if (ACPI_FAILURE(status)) 1064 if (err < 0)
1098 return -EIO; 1065 return err;
1099 1066
1100 seq_printf(m, "DSTS(%x) = %x\n", asus->debug.dev_id, retval); 1067 seq_printf(m, "DSTS(%x) = %x\n", asus->debug.dev_id, retval);
1101 1068
@@ -1105,13 +1072,14 @@ static int show_dsts(struct seq_file *m, void *data)
1105static int show_devs(struct seq_file *m, void *data) 1072static int show_devs(struct seq_file *m, void *data)
1106{ 1073{
1107 struct asus_wmi *asus = m->private; 1074 struct asus_wmi *asus = m->private;
1108 acpi_status status; 1075 int err;
1109 u32 retval = -1; 1076 u32 retval = -1;
1110 1077
1111 status = asus_wmi_set_devstate(asus->debug.dev_id, 1078 err = asus_wmi_set_devstate(asus->debug.dev_id, asus->debug.ctrl_param,
1112 asus->debug.ctrl_param, &retval); 1079 &retval);
1113 if (ACPI_FAILURE(status)) 1080
1114 return -EIO; 1081 if (err < 0)
1082 return err;
1115 1083
1116 seq_printf(m, "DEVS(%x, %x) = %x\n", asus->debug.dev_id, 1084 seq_printf(m, "DEVS(%x, %x) = %x\n", asus->debug.dev_id,
1117 asus->debug.ctrl_param, retval); 1085 asus->debug.ctrl_param, retval);