aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform/x86
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/platform/x86')
-rw-r--r--drivers/platform/x86/asus-wmi.c99
1 files changed, 66 insertions, 33 deletions
diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
index 34e6b4d83a9..fd5b08eecf1 100644
--- a/drivers/platform/x86/asus-wmi.c
+++ b/drivers/platform/x86/asus-wmi.c
@@ -67,6 +67,7 @@ MODULE_LICENSE("GPL");
67 67
68/* WMI Methods */ 68/* WMI Methods */
69#define ASUS_WMI_METHODID_DSTS 0x53544344 69#define ASUS_WMI_METHODID_DSTS 0x53544344
70#define ASUS_WMI_METHODID_DSTS2 0x53545344
70#define ASUS_WMI_METHODID_DEVS 0x53564544 71#define ASUS_WMI_METHODID_DEVS 0x53564544
71#define ASUS_WMI_METHODID_CFVS 0x53564643 72#define ASUS_WMI_METHODID_CFVS 0x53564643
72 73
@@ -124,6 +125,8 @@ struct asus_rfkill {
124}; 125};
125 126
126struct asus_wmi { 127struct asus_wmi {
128 int dsts_id;
129
127 struct input_dev *inputdev; 130 struct input_dev *inputdev;
128 struct backlight_device *backlight_device; 131 struct backlight_device *backlight_device;
129 struct platform_device *platform_device; 132 struct platform_device *platform_device;
@@ -229,26 +232,26 @@ exit:
229 return 0; 232 return 0;
230} 233}
231 234
232static int asus_wmi_get_devstate(u32 dev_id, u32 *retval) 235static int asus_wmi_get_devstate(struct asus_wmi *asus, u32 dev_id, u32 *retval)
233{ 236{
234 return asus_wmi_evaluate_method(ASUS_WMI_METHODID_DSTS, dev_id, 237 return asus_wmi_evaluate_method(asus->dsts_id, dev_id, 0, retval);
235 0, retval);
236} 238}
237 239
238static int asus_wmi_set_devstate(u32 dev_id, u32 ctrl_param, 240static int asus_wmi_set_devstate(u32 dev_id, u32 ctrl_param,
239 u32 *retval) 241 u32 *retval)
240{ 242{
241 return asus_wmi_evaluate_method(ASUS_WMI_METHODID_DEVS, dev_id, 243 return asus_wmi_evaluate_method(ASUS_WMI_METHODID_DEVS, dev_id,
242 ctrl_param, retval); 244 ctrl_param, retval);
243} 245}
244 246
245/* Helper for special devices with magic return codes */ 247/* Helper for special devices with magic return codes */
246static int asus_wmi_get_devstate_bits(u32 dev_id, u32 mask) 248static int asus_wmi_get_devstate_bits(struct asus_wmi *asus,
249 u32 dev_id, u32 mask)
247{ 250{
248 u32 retval = 0; 251 u32 retval = 0;
249 int err; 252 int err;
250 253
251 err = asus_wmi_get_devstate(dev_id, &retval); 254 err = asus_wmi_get_devstate(asus, dev_id, &retval);
252 255
253 if (err < 0) 256 if (err < 0)
254 return err; 257 return err;
@@ -264,9 +267,10 @@ static int asus_wmi_get_devstate_bits(u32 dev_id, u32 mask)
264 return retval & mask; 267 return retval & mask;
265} 268}
266 269
267static int asus_wmi_get_devstate_simple(u32 dev_id) 270static int asus_wmi_get_devstate_simple(struct asus_wmi *asus, u32 dev_id)
268{ 271{
269 return asus_wmi_get_devstate_bits(dev_id, ASUS_WMI_DSTS_STATUS_BIT); 272 return asus_wmi_get_devstate_bits(asus, dev_id,
273 ASUS_WMI_DSTS_STATUS_BIT);
270} 274}
271 275
272/* 276/*
@@ -302,7 +306,7 @@ static void tpd_led_set(struct led_classdev *led_cdev,
302 306
303static int read_tpd_led_state(struct asus_wmi *asus) 307static int read_tpd_led_state(struct asus_wmi *asus)
304{ 308{
305 return asus_wmi_get_devstate_simple(ASUS_WMI_DEVID_TOUCHPAD_LED); 309 return asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_TOUCHPAD_LED);
306} 310}
307 311
308static enum led_brightness tpd_led_get(struct led_classdev *led_cdev) 312static enum led_brightness tpd_led_get(struct led_classdev *led_cdev)
@@ -353,7 +357,7 @@ static void asus_wmi_led_exit(struct asus_wmi *asus)
353 */ 357 */
354static bool asus_wlan_rfkill_blocked(struct asus_wmi *asus) 358static bool asus_wlan_rfkill_blocked(struct asus_wmi *asus)
355{ 359{
356 int result = asus_wmi_get_devstate_simple(ASUS_WMI_DEVID_WLAN); 360 int result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_WLAN);
357 361
358 if (result < 0) 362 if (result < 0)
359 return false; 363 return false;
@@ -482,7 +486,8 @@ static void asus_unregister_rfkill_notifier(struct asus_wmi *asus, char *node)
482static int asus_get_adapter_status(struct hotplug_slot *hotplug_slot, 486static int asus_get_adapter_status(struct hotplug_slot *hotplug_slot,
483 u8 *value) 487 u8 *value)
484{ 488{
485 int result = asus_wmi_get_devstate_simple(ASUS_WMI_DEVID_WLAN); 489 struct asus_wmi *asus = hotplug_slot->private;
490 int result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_WLAN);
486 491
487 if (result < 0) 492 if (result < 0)
488 return result; 493 return result;
@@ -578,7 +583,7 @@ static void asus_rfkill_query(struct rfkill *rfkill, void *data)
578 struct asus_rfkill *priv = data; 583 struct asus_rfkill *priv = data;
579 int result; 584 int result;
580 585
581 result = asus_wmi_get_devstate_simple(priv->dev_id); 586 result = asus_wmi_get_devstate_simple(priv->asus, priv->dev_id);
582 587
583 if (result < 0) 588 if (result < 0)
584 return; 589 return;
@@ -619,7 +624,7 @@ static int asus_new_rfkill(struct asus_wmi *asus,
619 struct asus_rfkill *arfkill, 624 struct asus_rfkill *arfkill,
620 const char *name, enum rfkill_type type, int dev_id) 625 const char *name, enum rfkill_type type, int dev_id)
621{ 626{
622 int result = asus_wmi_get_devstate_simple(dev_id); 627 int result = asus_wmi_get_devstate_simple(asus, dev_id);
623 struct rfkill **rfkill = &arfkill->rfkill; 628 struct rfkill **rfkill = &arfkill->rfkill;
624 629
625 if (result < 0) 630 if (result < 0)
@@ -750,9 +755,9 @@ exit:
750/* 755/*
751 * Backlight 756 * Backlight
752 */ 757 */
753static int read_backlight_power(void) 758static int read_backlight_power(struct asus_wmi *asus)
754{ 759{
755 int ret = asus_wmi_get_devstate_simple(ASUS_WMI_DEVID_BACKLIGHT); 760 int ret = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_BACKLIGHT);
756 761
757 if (ret < 0) 762 if (ret < 0)
758 return ret; 763 return ret;
@@ -762,10 +767,11 @@ static int read_backlight_power(void)
762 767
763static int read_brightness(struct backlight_device *bd) 768static int read_brightness(struct backlight_device *bd)
764{ 769{
770 struct asus_wmi *asus = bl_get_data(bd);
765 u32 retval; 771 u32 retval;
766 int err; 772 int err;
767 773
768 err = asus_wmi_get_devstate(ASUS_WMI_DEVID_BRIGHTNESS, &retval); 774 err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_BRIGHTNESS, &retval);
769 775
770 if (err < 0) 776 if (err < 0)
771 return err; 777 return err;
@@ -775,6 +781,7 @@ static int read_brightness(struct backlight_device *bd)
775 781
776static int update_bl_status(struct backlight_device *bd) 782static int update_bl_status(struct backlight_device *bd)
777{ 783{
784 struct asus_wmi *asus = bl_get_data(bd);
778 u32 ctrl_param; 785 u32 ctrl_param;
779 int power, err; 786 int power, err;
780 787
@@ -786,7 +793,7 @@ static int update_bl_status(struct backlight_device *bd)
786 if (err < 0) 793 if (err < 0)
787 return err; 794 return err;
788 795
789 power = read_backlight_power(); 796 power = read_backlight_power(asus);
790 if (power != -ENODEV && bd->props.power != power) { 797 if (power != -ENODEV && bd->props.power != power) {
791 ctrl_param = !!(bd->props.power == FB_BLANK_UNBLANK); 798 ctrl_param = !!(bd->props.power == FB_BLANK_UNBLANK);
792 err = asus_wmi_set_devstate(ASUS_WMI_DEVID_BACKLIGHT, 799 err = asus_wmi_set_devstate(ASUS_WMI_DEVID_BACKLIGHT,
@@ -825,9 +832,9 @@ static int asus_wmi_backlight_init(struct asus_wmi *asus)
825 int max; 832 int max;
826 int power; 833 int power;
827 834
828 max = asus_wmi_get_devstate_bits(ASUS_WMI_DEVID_BRIGHTNESS, 835 max = asus_wmi_get_devstate_bits(asus, ASUS_WMI_DEVID_BRIGHTNESS,
829 ASUS_WMI_DSTS_MAX_BRIGTH_MASK); 836 ASUS_WMI_DSTS_MAX_BRIGTH_MASK);
830 power = read_backlight_power(); 837 power = read_backlight_power(asus);
831 838
832 if (max < 0 && power < 0) { 839 if (max < 0 && power < 0) {
833 /* Try to keep the original error */ 840 /* Try to keep the original error */
@@ -921,12 +928,13 @@ static int parse_arg(const char *buf, unsigned long count, int *val)
921 return count; 928 return count;
922} 929}
923 930
924static ssize_t store_sys_wmi(int devid, const char *buf, size_t count) 931static ssize_t store_sys_wmi(struct asus_wmi *asus, int devid,
932 const char *buf, size_t count)
925{ 933{
926 u32 retval; 934 u32 retval;
927 int rv, err, value; 935 int rv, err, value;
928 936
929 value = asus_wmi_get_devstate_simple(devid); 937 value = asus_wmi_get_devstate_simple(asus, devid);
930 if (value == -ENODEV) /* Check device presence */ 938 if (value == -ENODEV) /* Check device presence */
931 return value; 939 return value;
932 940
@@ -939,9 +947,9 @@ static ssize_t store_sys_wmi(int devid, const char *buf, size_t count)
939 return rv; 947 return rv;
940} 948}
941 949
942static ssize_t show_sys_wmi(int devid, char *buf) 950static ssize_t show_sys_wmi(struct asus_wmi *asus, int devid, char *buf)
943{ 951{
944 int value = asus_wmi_get_devstate_simple(devid); 952 int value = asus_wmi_get_devstate_simple(asus, devid);
945 953
946 if (value < 0) 954 if (value < 0)
947 return value; 955 return value;
@@ -954,13 +962,17 @@ static ssize_t show_sys_wmi(int devid, char *buf)
954 struct device_attribute *attr, \ 962 struct device_attribute *attr, \
955 char *buf) \ 963 char *buf) \
956 { \ 964 { \
957 return show_sys_wmi(_cm, buf); \ 965 struct asus_wmi *asus = dev_get_drvdata(dev); \
966 \
967 return show_sys_wmi(asus, _cm, buf); \
958 } \ 968 } \
959 static ssize_t store_##_name(struct device *dev, \ 969 static ssize_t store_##_name(struct device *dev, \
960 struct device_attribute *attr, \ 970 struct device_attribute *attr, \
961 const char *buf, size_t count) \ 971 const char *buf, size_t count) \
962 { \ 972 { \
963 return store_sys_wmi(_cm, buf, count); \ 973 struct asus_wmi *asus = dev_get_drvdata(dev); \
974 \
975 return store_sys_wmi(asus, _cm, buf, count); \
964 } \ 976 } \
965 static struct device_attribute dev_attr_##_name = { \ 977 static struct device_attribute dev_attr_##_name = { \
966 .attr = { \ 978 .attr = { \
@@ -1000,7 +1012,10 @@ static struct attribute *platform_attributes[] = {
1000static mode_t asus_sysfs_is_visible(struct kobject *kobj, 1012static mode_t asus_sysfs_is_visible(struct kobject *kobj,
1001 struct attribute *attr, int idx) 1013 struct attribute *attr, int idx)
1002{ 1014{
1003 bool supported = true; 1015 struct device *dev = container_of(kobj, struct device, kobj);
1016 struct platform_device *pdev = to_platform_device(dev);
1017 struct asus_wmi *asus = platform_get_drvdata(pdev);
1018 bool ok = true;
1004 int devid = -1; 1019 int devid = -1;
1005 1020
1006 if (attr == &dev_attr_camera.attr) 1021 if (attr == &dev_attr_camera.attr)
@@ -1011,9 +1026,9 @@ static mode_t asus_sysfs_is_visible(struct kobject *kobj,
1011 devid = ASUS_WMI_DEVID_TOUCHPAD; 1026 devid = ASUS_WMI_DEVID_TOUCHPAD;
1012 1027
1013 if (devid != -1) 1028 if (devid != -1)
1014 supported = asus_wmi_get_devstate_simple(devid) != -ENODEV; 1029 ok = !(asus_wmi_get_devstate_simple(asus, devid) < 0);
1015 1030
1016 return supported ? attr->mode : 0; 1031 return ok ? attr->mode : 0;
1017} 1032}
1018 1033
1019static struct attribute_group platform_attribute_group = { 1034static struct attribute_group platform_attribute_group = {
@@ -1036,6 +1051,23 @@ static int asus_wmi_sysfs_init(struct platform_device *device)
1036 */ 1051 */
1037static int __init asus_wmi_platform_init(struct asus_wmi *asus) 1052static int __init asus_wmi_platform_init(struct asus_wmi *asus)
1038{ 1053{
1054 /*
1055 * Eee PC and Notebooks seems to have different method_id for DSTS,
1056 * but it may also be related to the BIOS's SPEC.
1057 * Note, on most Eeepc, there is no way to check if a method exist
1058 * or note, while on notebooks, they returns 0xFFFFFFFE on failure,
1059 * but once again, SPEC may probably be used for that kind of things.
1060 */
1061 if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_DSTS, 0, 0, NULL))
1062 asus->dsts_id = ASUS_WMI_METHODID_DSTS;
1063 else if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_DSTS2, 0, 0, NULL))
1064 asus->dsts_id = ASUS_WMI_METHODID_DSTS2;
1065
1066 if (!asus->dsts_id) {
1067 pr_err("Can't find DSTS");
1068 return -ENODEV;
1069 }
1070
1039 return asus_wmi_sysfs_init(asus->platform_device); 1071 return asus_wmi_sysfs_init(asus->platform_device);
1040} 1072}
1041 1073
@@ -1059,7 +1091,7 @@ static int show_dsts(struct seq_file *m, void *data)
1059 int err; 1091 int err;
1060 u32 retval = -1; 1092 u32 retval = -1;
1061 1093
1062 err = asus_wmi_get_devstate(asus->debug.dev_id, &retval); 1094 err = asus_wmi_get_devstate(asus, asus->debug.dev_id, &retval);
1063 1095
1064 if (err < 0) 1096 if (err < 0)
1065 return err; 1097 return err;
@@ -1262,7 +1294,7 @@ static int asus_hotk_thaw(struct device *device)
1262 * during suspend. Normally it restores it on resume, but 1294 * during suspend. Normally it restores it on resume, but
1263 * we should kick it ourselves in case hibernation is aborted. 1295 * we should kick it ourselves in case hibernation is aborted.
1264 */ 1296 */
1265 wlan = asus_wmi_get_devstate_simple(ASUS_WMI_DEVID_WLAN); 1297 wlan = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_WLAN);
1266 asus_wmi_set_devstate(ASUS_WMI_DEVID_WLAN, wlan, NULL); 1298 asus_wmi_set_devstate(ASUS_WMI_DEVID_WLAN, wlan, NULL);
1267 } 1299 }
1268 1300
@@ -1279,15 +1311,16 @@ static int asus_hotk_restore(struct device *device)
1279 asus_rfkill_hotplug(asus); 1311 asus_rfkill_hotplug(asus);
1280 1312
1281 if (asus->bluetooth.rfkill) { 1313 if (asus->bluetooth.rfkill) {
1282 bl = !asus_wmi_get_devstate_simple(ASUS_WMI_DEVID_BLUETOOTH); 1314 bl = !asus_wmi_get_devstate_simple(asus,
1315 ASUS_WMI_DEVID_BLUETOOTH);
1283 rfkill_set_sw_state(asus->bluetooth.rfkill, bl); 1316 rfkill_set_sw_state(asus->bluetooth.rfkill, bl);
1284 } 1317 }
1285 if (asus->wimax.rfkill) { 1318 if (asus->wimax.rfkill) {
1286 bl = !asus_wmi_get_devstate_simple(ASUS_WMI_DEVID_WIMAX); 1319 bl = !asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_WIMAX);
1287 rfkill_set_sw_state(asus->wimax.rfkill, bl); 1320 rfkill_set_sw_state(asus->wimax.rfkill, bl);
1288 } 1321 }
1289 if (asus->wwan3g.rfkill) { 1322 if (asus->wwan3g.rfkill) {
1290 bl = !asus_wmi_get_devstate_simple(ASUS_WMI_DEVID_WWAN3G); 1323 bl = !asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_WWAN3G);
1291 rfkill_set_sw_state(asus->wwan3g.rfkill, bl); 1324 rfkill_set_sw_state(asus->wwan3g.rfkill, bl);
1292 } 1325 }
1293 1326