aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorChris Bagwell <chris@cnpbagwell.com>2010-10-11 19:47:18 -0400
committerMatthew Garrett <mjg@redhat.com>2010-10-21 10:10:53 -0400
commit7f80d734b3b5d23b9851cc03cc20733bca2c724e (patch)
tree406b97e43f8e2db6ab7ca5cf3433e41532f9e699 /drivers
parenteda1748418beb1b9a75d0cea3304edf922c66134 (diff)
eeepc-wmi: Add cpufv sysfs interface
eeepc-laptop provides a sysfs interface to read and control what it calls cpufv. When WMI is enabled, the ACPI interface changes slightly and becames a write-only control with 3 valid values. Expose cpufv again to allow for user space utils that can extended battery life noticably and come a little closer to parity with eeepc-laptop. Write-only is OK for most user space apps because read status was mostly used to prevent unneeded mode changes. Since this same check to ignore changes to same mode also exists in the DSDT then it was wasted ACPI call. acpi_osi="!Windows 2009" can be used for get back eeepc-laptop's read support of cpufv for debugging things such as behaviour during resume. This patch was tested with EEE PC 1005PE by monitoring powertop output while writing values of "0", "1", and "2" and by reviewing the decompiled DSDT of an 1201NL and comparing it to 1005PE's DSDT. Signed-off-by: Chris Bagwell <chris@cnpbagwell.com> Signed-off-by: Matthew Garrett <mjg@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/platform/x86/eeepc-wmi.c51
1 files changed, 51 insertions, 0 deletions
diff --git a/drivers/platform/x86/eeepc-wmi.c b/drivers/platform/x86/eeepc-wmi.c
index 21df266c27ac..462ceab93f87 100644
--- a/drivers/platform/x86/eeepc-wmi.c
+++ b/drivers/platform/x86/eeepc-wmi.c
@@ -57,6 +57,7 @@ MODULE_ALIAS("wmi:"EEEPC_WMI_MGMT_GUID);
57 57
58#define EEEPC_WMI_METHODID_DEVS 0x53564544 58#define EEEPC_WMI_METHODID_DEVS 0x53564544
59#define EEEPC_WMI_METHODID_DSTS 0x53544344 59#define EEEPC_WMI_METHODID_DSTS 0x53544344
60#define EEEPC_WMI_METHODID_CFVS 0x53564643
60 61
61#define EEEPC_WMI_DEVID_BACKLIGHT 0x00050012 62#define EEEPC_WMI_DEVID_BACKLIGHT 0x00050012
62 63
@@ -297,6 +298,49 @@ static void eeepc_wmi_notify(u32 value, void *context)
297 kfree(obj); 298 kfree(obj);
298} 299}
299 300
301static int store_cpufv(struct device *dev, struct device_attribute *attr,
302 const char *buf, size_t count)
303{
304 int value;
305 struct acpi_buffer input = { (acpi_size)sizeof(value), &value };
306 acpi_status status;
307
308 if (!count || sscanf(buf, "%i", &value) != 1)
309 return -EINVAL;
310 if (value < 0 || value > 2)
311 return -EINVAL;
312
313 status = wmi_evaluate_method(EEEPC_WMI_MGMT_GUID,
314 1, EEEPC_WMI_METHODID_CFVS, &input, NULL);
315
316 if (ACPI_FAILURE(status))
317 return -EIO;
318 else
319 return count;
320}
321
322static DEVICE_ATTR(cpufv, S_IRUGO | S_IWUSR, NULL, store_cpufv);
323
324static void eeepc_wmi_sysfs_exit(struct platform_device *device)
325{
326 device_remove_file(&device->dev, &dev_attr_cpufv);
327}
328
329static int eeepc_wmi_sysfs_init(struct platform_device *device)
330{
331 int retval = -ENOMEM;
332
333 retval = device_create_file(&device->dev, &dev_attr_cpufv);
334 if (retval)
335 goto error_sysfs;
336
337 return 0;
338
339error_sysfs:
340 eeepc_wmi_sysfs_exit(platform_device);
341 return retval;
342}
343
300static int __devinit eeepc_wmi_platform_probe(struct platform_device *device) 344static int __devinit eeepc_wmi_platform_probe(struct platform_device *device)
301{ 345{
302 struct eeepc_wmi *eeepc; 346 struct eeepc_wmi *eeepc;
@@ -392,8 +436,14 @@ static int __init eeepc_wmi_init(void)
392 goto del_dev; 436 goto del_dev;
393 } 437 }
394 438
439 err = eeepc_wmi_sysfs_init(platform_device);
440 if (err)
441 goto del_sysfs;
442
395 return 0; 443 return 0;
396 444
445del_sysfs:
446 eeepc_wmi_sysfs_exit(platform_device);
397del_dev: 447del_dev:
398 platform_device_del(platform_device); 448 platform_device_del(platform_device);
399put_dev: 449put_dev:
@@ -408,6 +458,7 @@ static void __exit eeepc_wmi_exit(void)
408{ 458{
409 struct eeepc_wmi *eeepc; 459 struct eeepc_wmi *eeepc;
410 460
461 eeepc_wmi_sysfs_exit(platform_device);
411 eeepc = platform_get_drvdata(platform_device); 462 eeepc = platform_get_drvdata(platform_device);
412 platform_driver_unregister(&platform_driver); 463 platform_driver_unregister(&platform_driver);
413 platform_device_unregister(platform_device); 464 platform_device_unregister(platform_device);