eeepc-laptop: cpufv updates
authorCorentin Chary <corentincj@iksaif.net>
Tue, 16 Jun 2009 19:28:56 +0000 (19:28 +0000)
committerLen Brown <len.brown@intel.com>
Wed, 24 Jun 2009 05:31:21 +0000 (01:31 -0400)
Limit cpufv input to acceptables values.
Add an available_cpufv file to show available
presets.
Change cpufv ouput format from %d to %#x, it won't
break compatibility with existing userspace tools, but
it provide a more human readable output.

Signed-off-by: Corentin Chary <corentincj@iksaif.net>
Signed-off-by: Len Brown <len.brown@intel.com>
drivers/platform/x86/eeepc-laptop.c

index 73f3cb0..4207b26 100644 (file)
@@ -392,13 +392,88 @@ static ssize_t show_sys_acpi(int cm, char *buf)
 EEEPC_CREATE_DEVICE_ATTR(camera, CM_ASL_CAMERA);
 EEEPC_CREATE_DEVICE_ATTR(cardr, CM_ASL_CARDREADER);
 EEEPC_CREATE_DEVICE_ATTR(disp, CM_ASL_DISPLAYSWITCH);
 EEEPC_CREATE_DEVICE_ATTR(camera, CM_ASL_CAMERA);
 EEEPC_CREATE_DEVICE_ATTR(cardr, CM_ASL_CARDREADER);
 EEEPC_CREATE_DEVICE_ATTR(disp, CM_ASL_DISPLAYSWITCH);
-EEEPC_CREATE_DEVICE_ATTR(cpufv, CM_ASL_CPUFV);
+
+struct eeepc_cpufv {
+       int num;
+       int cur;
+};
+
+static int get_cpufv(struct eeepc_cpufv *c)
+{
+       c->cur = get_acpi(CM_ASL_CPUFV);
+       c->num = (c->cur >> 8) & 0xff;
+       c->cur &= 0xff;
+       if (c->cur < 0 || c->num <= 0 || c->num > 12)
+               return -ENODEV;
+       return 0;
+}
+
+static ssize_t show_available_cpufv(struct device *dev,
+                                   struct device_attribute *attr,
+                                   char *buf)
+{
+       struct eeepc_cpufv c;
+       int i;
+       ssize_t len = 0;
+
+       if (get_cpufv(&c))
+               return -ENODEV;
+       for (i = 0; i < c.num; i++)
+               len += sprintf(buf + len, "%d ", i);
+       len += sprintf(buf + len, "\n");
+       return len;
+}
+
+static ssize_t show_cpufv(struct device *dev,
+                         struct device_attribute *attr,
+                         char *buf)
+{
+       struct eeepc_cpufv c;
+
+       if (get_cpufv(&c))
+               return -ENODEV;
+       return sprintf(buf, "%#x\n", (c.num << 8) | c.cur);
+}
+
+static ssize_t store_cpufv(struct device *dev,
+                          struct device_attribute *attr,
+                          const char *buf, size_t count)
+{
+       struct eeepc_cpufv c;
+       int rv, value;
+
+       if (get_cpufv(&c))
+               return -ENODEV;
+       rv = parse_arg(buf, count, &value);
+       if (rv < 0)
+               return rv;
+       if (!rv || value < 0 || value >= c.num)
+               return -EINVAL;
+       set_acpi(CM_ASL_CPUFV, value);
+       return rv;
+}
+
+static struct device_attribute dev_attr_cpufv = {
+       .attr = {
+               .name = "cpufv",
+               .mode = 0644 },
+       .show   = show_cpufv,
+       .store  = store_cpufv
+};
+
+static struct device_attribute dev_attr_available_cpufv = {
+       .attr = {
+               .name = "available_cpufv",
+               .mode = 0444 },
+       .show   = show_available_cpufv
+};
 
 static struct attribute *platform_attributes[] = {
        &dev_attr_camera.attr,
        &dev_attr_cardr.attr,
        &dev_attr_disp.attr,
        &dev_attr_cpufv.attr,
 
 static struct attribute *platform_attributes[] = {
        &dev_attr_camera.attr,
        &dev_attr_cardr.attr,
        &dev_attr_disp.attr,
        &dev_attr_cpufv.attr,
+       &dev_attr_available_cpufv.attr,
        NULL
 };
 
        NULL
 };