aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/platform/x86/eeepc-wmi.c170
1 files changed, 164 insertions, 6 deletions
diff --git a/drivers/platform/x86/eeepc-wmi.c b/drivers/platform/x86/eeepc-wmi.c
index a70d76a463a6..253070ab963c 100644
--- a/drivers/platform/x86/eeepc-wmi.c
+++ b/drivers/platform/x86/eeepc-wmi.c
@@ -36,6 +36,8 @@
36#include <linux/backlight.h> 36#include <linux/backlight.h>
37#include <linux/leds.h> 37#include <linux/leds.h>
38#include <linux/rfkill.h> 38#include <linux/rfkill.h>
39#include <linux/debugfs.h>
40#include <linux/seq_file.h>
39#include <linux/platform_device.h> 41#include <linux/platform_device.h>
40#include <acpi/acpi_bus.h> 42#include <acpi/acpi_bus.h>
41#include <acpi/acpi_drivers.h> 43#include <acpi/acpi_drivers.h>
@@ -89,6 +91,19 @@ struct bios_args {
89 u32 ctrl_param; 91 u32 ctrl_param;
90}; 92};
91 93
94/*
95 * eeepc-wmi/ - debugfs root directory
96 * dev_id - current dev_id
97 * ctrl_param - current ctrl_param
98 * devs - call DEVS(dev_id, ctrl_param) and print result
99 * dsts - call DSTS(dev_id) and print result
100 */
101struct eeepc_wmi_debug {
102 struct dentry *root;
103 u32 dev_id;
104 u32 ctrl_param;
105};
106
92struct eeepc_wmi { 107struct eeepc_wmi {
93 struct input_dev *inputdev; 108 struct input_dev *inputdev;
94 struct backlight_device *backlight_device; 109 struct backlight_device *backlight_device;
@@ -102,6 +117,8 @@ struct eeepc_wmi {
102 struct rfkill *wlan_rfkill; 117 struct rfkill *wlan_rfkill;
103 struct rfkill *bluetooth_rfkill; 118 struct rfkill *bluetooth_rfkill;
104 struct rfkill *wwan3g_rfkill; 119 struct rfkill *wwan3g_rfkill;
120
121 struct eeepc_wmi_debug debug;
105}; 122};
106 123
107/* Only used in eeepc_wmi_init() and eeepc_wmi_exit() */ 124/* Only used in eeepc_wmi_init() and eeepc_wmi_exit() */
@@ -176,7 +193,8 @@ static acpi_status eeepc_wmi_get_devstate(u32 dev_id, u32 *ctrl_param)
176 193
177} 194}
178 195
179static acpi_status eeepc_wmi_set_devstate(u32 dev_id, u32 ctrl_param) 196static acpi_status eeepc_wmi_set_devstate(u32 dev_id, u32 ctrl_param,
197 u32 *retval)
180{ 198{
181 struct bios_args args = { 199 struct bios_args args = {
182 .dev_id = dev_id, 200 .dev_id = dev_id,
@@ -185,8 +203,32 @@ static acpi_status eeepc_wmi_set_devstate(u32 dev_id, u32 ctrl_param)
185 struct acpi_buffer input = { (acpi_size)sizeof(args), &args }; 203 struct acpi_buffer input = { (acpi_size)sizeof(args), &args };
186 acpi_status status; 204 acpi_status status;
187 205
188 status = wmi_evaluate_method(EEEPC_WMI_MGMT_GUID, 206 if (!retval) {
189 1, EEEPC_WMI_METHODID_DEVS, &input, NULL); 207 status = wmi_evaluate_method(EEEPC_WMI_MGMT_GUID, 1,
208 EEEPC_WMI_METHODID_DEVS,
209 &input, NULL);
210 } else {
211 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
212 union acpi_object *obj;
213 u32 tmp;
214
215 status = wmi_evaluate_method(EEEPC_WMI_MGMT_GUID, 1,
216 EEEPC_WMI_METHODID_DEVS,
217 &input, &output);
218
219 if (ACPI_FAILURE(status))
220 return status;
221
222 obj = (union acpi_object *)output.pointer;
223 if (obj && obj->type == ACPI_TYPE_INTEGER)
224 tmp = (u32)obj->integer.value;
225 else
226 tmp = 0;
227
228 *retval = tmp;
229
230 kfree(obj);
231 }
190 232
191 return status; 233 return status;
192} 234}
@@ -208,7 +250,7 @@ static void tpd_led_update(struct work_struct *work)
208 eeepc = container_of(work, struct eeepc_wmi, tpd_led_work); 250 eeepc = container_of(work, struct eeepc_wmi, tpd_led_work);
209 251
210 ctrl_param = eeepc->tpd_led_wk; 252 ctrl_param = eeepc->tpd_led_wk;
211 eeepc_wmi_set_devstate(EEEPC_WMI_DEVID_TPDLED, ctrl_param); 253 eeepc_wmi_set_devstate(EEEPC_WMI_DEVID_TPDLED, ctrl_param, NULL);
212} 254}
213 255
214static void tpd_led_set(struct led_classdev *led_cdev, 256static void tpd_led_set(struct led_classdev *led_cdev,
@@ -295,7 +337,7 @@ static int eeepc_rfkill_set(void *data, bool blocked)
295 int dev_id = (unsigned long)data; 337 int dev_id = (unsigned long)data;
296 u32 ctrl_param = !blocked; 338 u32 ctrl_param = !blocked;
297 339
298 return eeepc_wmi_set_devstate(dev_id, ctrl_param); 340 return eeepc_wmi_set_devstate(dev_id, ctrl_param, NULL);
299} 341}
300 342
301static void eeepc_rfkill_query(struct rfkill *rfkill, void *data) 343static void eeepc_rfkill_query(struct rfkill *rfkill, void *data)
@@ -434,7 +476,8 @@ static int update_bl_status(struct backlight_device *bd)
434 476
435 ctrl_param = bd->props.brightness; 477 ctrl_param = bd->props.brightness;
436 478
437 status = eeepc_wmi_set_devstate(EEEPC_WMI_DEVID_BACKLIGHT, ctrl_param); 479 status = eeepc_wmi_set_devstate(EEEPC_WMI_DEVID_BACKLIGHT,
480 ctrl_param, NULL);
438 481
439 if (ACPI_FAILURE(status)) 482 if (ACPI_FAILURE(status))
440 return -1; 483 return -1;
@@ -614,6 +657,114 @@ static void eeepc_wmi_platform_exit(struct eeepc_wmi *eeepc)
614} 657}
615 658
616/* 659/*
660 * debugfs
661 */
662struct eeepc_wmi_debugfs_node {
663 struct eeepc_wmi *eeepc;
664 char *name;
665 int (*show)(struct seq_file *m, void *data);
666};
667
668static int show_dsts(struct seq_file *m, void *data)
669{
670 struct eeepc_wmi *eeepc = m->private;
671 acpi_status status;
672 u32 retval = -1;
673
674 status = eeepc_wmi_get_devstate(eeepc->debug.dev_id, &retval);
675
676 if (ACPI_FAILURE(status))
677 return -EIO;
678
679 seq_printf(m, "DSTS(%x) = %x\n", eeepc->debug.dev_id, retval);
680
681 return 0;
682}
683
684static int show_devs(struct seq_file *m, void *data)
685{
686 struct eeepc_wmi *eeepc = m->private;
687 acpi_status status;
688 u32 retval = -1;
689
690 status = eeepc_wmi_set_devstate(eeepc->debug.dev_id,
691 eeepc->debug.ctrl_param, &retval);
692 if (ACPI_FAILURE(status))
693 return -EIO;
694
695 seq_printf(m, "DEVS(%x, %x) = %x\n", eeepc->debug.dev_id,
696 eeepc->debug.ctrl_param, retval);
697
698 return 0;
699}
700
701static struct eeepc_wmi_debugfs_node eeepc_wmi_debug_files[] = {
702 { NULL, "devs", show_devs },
703 { NULL, "dsts", show_dsts },
704};
705
706static int eeepc_wmi_debugfs_open(struct inode *inode, struct file *file)
707{
708 struct eeepc_wmi_debugfs_node *node = inode->i_private;
709
710 return single_open(file, node->show, node->eeepc);
711}
712
713static const struct file_operations eeepc_wmi_debugfs_io_ops = {
714 .owner = THIS_MODULE,
715 .open = eeepc_wmi_debugfs_open,
716 .read = seq_read,
717 .llseek = seq_lseek,
718 .release = single_release,
719};
720
721static void eeepc_wmi_debugfs_exit(struct eeepc_wmi *eeepc)
722{
723 debugfs_remove_recursive(eeepc->debug.root);
724}
725
726static int eeepc_wmi_debugfs_init(struct eeepc_wmi *eeepc)
727{
728 struct dentry *dent;
729 int i;
730
731 eeepc->debug.root = debugfs_create_dir(EEEPC_WMI_FILE, NULL);
732 if (!eeepc->debug.root) {
733 pr_err("failed to create debugfs directory");
734 goto error_debugfs;
735 }
736
737 dent = debugfs_create_x32("dev_id", S_IRUGO|S_IWUSR,
738 eeepc->debug.root, &eeepc->debug.dev_id);
739 if (!dent)
740 goto error_debugfs;
741
742 dent = debugfs_create_x32("ctrl_param", S_IRUGO|S_IWUSR,
743 eeepc->debug.root, &eeepc->debug.ctrl_param);
744 if (!dent)
745 goto error_debugfs;
746
747 for (i = 0; i < ARRAY_SIZE(eeepc_wmi_debug_files); i++) {
748 struct eeepc_wmi_debugfs_node *node = &eeepc_wmi_debug_files[i];
749
750 node->eeepc = eeepc;
751 dent = debugfs_create_file(node->name, S_IFREG | S_IRUGO,
752 eeepc->debug.root, node,
753 &eeepc_wmi_debugfs_io_ops);
754 if (!dent) {
755 pr_err("failed to create debug file: %s\n", node->name);
756 goto error_debugfs;
757 }
758 }
759
760 return 0;
761
762error_debugfs:
763 eeepc_wmi_debugfs_exit(eeepc);
764 return -ENOMEM;
765}
766
767/*
617 * WMI Driver 768 * WMI Driver
618 */ 769 */
619static struct platform_device * __init eeepc_wmi_add(void) 770static struct platform_device * __init eeepc_wmi_add(void)
@@ -662,8 +813,14 @@ static struct platform_device * __init eeepc_wmi_add(void)
662 goto fail_wmi_handler; 813 goto fail_wmi_handler;
663 } 814 }
664 815
816 err = eeepc_wmi_debugfs_init(eeepc);
817 if (err)
818 goto fail_debugfs;
819
665 return eeepc->platform_device; 820 return eeepc->platform_device;
666 821
822fail_debugfs:
823 wmi_remove_notify_handler(EEEPC_WMI_EVENT_GUID);
667fail_wmi_handler: 824fail_wmi_handler:
668 eeepc_wmi_backlight_exit(eeepc); 825 eeepc_wmi_backlight_exit(eeepc);
669fail_backlight: 826fail_backlight:
@@ -689,6 +846,7 @@ static int eeepc_wmi_remove(struct platform_device *device)
689 eeepc_wmi_input_exit(eeepc); 846 eeepc_wmi_input_exit(eeepc);
690 eeepc_wmi_led_exit(eeepc); 847 eeepc_wmi_led_exit(eeepc);
691 eeepc_wmi_rfkill_exit(eeepc); 848 eeepc_wmi_rfkill_exit(eeepc);
849 eeepc_wmi_debugfs_exit(eeepc);
692 eeepc_wmi_platform_exit(eeepc); 850 eeepc_wmi_platform_exit(eeepc);
693 851
694 kfree(eeepc); 852 kfree(eeepc);