eeepc-wmi: Add cpufv sysfs interface
[pandora-kernel.git] / drivers / platform / x86 / eeepc-wmi.c
index 9dc50fb..462ceab 100644 (file)
@@ -57,6 +57,7 @@ MODULE_ALIAS("wmi:"EEEPC_WMI_MGMT_GUID);
 
 #define EEEPC_WMI_METHODID_DEVS        0x53564544
 #define EEEPC_WMI_METHODID_DSTS        0x53544344
+#define EEEPC_WMI_METHODID_CFVS        0x53564643
 
 #define EEEPC_WMI_DEVID_BACKLIGHT      0x00050012
 
@@ -69,6 +70,11 @@ static const struct key_entry eeepc_wmi_keymap[] = {
        { KE_IGNORE, NOTIFY_BRNDOWN_MIN, { KEY_BRIGHTNESSDOWN } },
        { KE_IGNORE, NOTIFY_BRNUP_MIN, { KEY_BRIGHTNESSUP } },
        { KE_KEY, 0xcc, { KEY_SWITCHVIDEOMODE } },
+       { KE_KEY, 0x6b, { KEY_F13 } }, /* Disable Touchpad */
+       { KE_KEY, 0xe1, { KEY_F14 } },
+       { KE_KEY, 0xe9, { KEY_DISPLAY_OFF } },
+       { KE_KEY, 0xe0, { KEY_PROG1 } },
+       { KE_KEY, 0x5c, { KEY_F15 } },
        { KE_END, 0},
 };
 
@@ -292,6 +298,49 @@ static void eeepc_wmi_notify(u32 value, void *context)
        kfree(obj);
 }
 
+static int 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(EEEPC_WMI_MGMT_GUID,
+                                    1, EEEPC_WMI_METHODID_CFVS, &input, NULL);
+
+       if (ACPI_FAILURE(status))
+               return -EIO;
+       else
+               return count;
+}
+
+static DEVICE_ATTR(cpufv, S_IRUGO | S_IWUSR, NULL, store_cpufv);
+
+static void eeepc_wmi_sysfs_exit(struct platform_device *device)
+{
+       device_remove_file(&device->dev, &dev_attr_cpufv);
+}
+
+static int eeepc_wmi_sysfs_init(struct platform_device *device)
+{
+       int retval = -ENOMEM;
+
+       retval = device_create_file(&device->dev, &dev_attr_cpufv);
+       if (retval)
+               goto error_sysfs;
+
+       return 0;
+
+error_sysfs:
+       eeepc_wmi_sysfs_exit(platform_device);
+       return retval;
+}
+
 static int __devinit eeepc_wmi_platform_probe(struct platform_device *device)
 {
        struct eeepc_wmi *eeepc;
@@ -387,8 +436,14 @@ static int __init eeepc_wmi_init(void)
                goto del_dev;
        }
 
+       err = eeepc_wmi_sysfs_init(platform_device);
+       if (err)
+               goto del_sysfs;
+
        return 0;
 
+del_sysfs:
+       eeepc_wmi_sysfs_exit(platform_device);
 del_dev:
        platform_device_del(platform_device);
 put_dev:
@@ -403,6 +458,7 @@ static void __exit eeepc_wmi_exit(void)
 {
        struct eeepc_wmi *eeepc;
 
+       eeepc_wmi_sysfs_exit(platform_device);
        eeepc = platform_get_drvdata(platform_device);
        platform_driver_unregister(&platform_driver);
        platform_device_unregister(platform_device);