diff options
-rw-r--r-- | Documentation/ABI/testing/sysfs-driver-samsung-laptop | 10 | ||||
-rw-r--r-- | drivers/platform/x86/samsung-laptop.c | 82 |
2 files changed, 92 insertions, 0 deletions
diff --git a/Documentation/ABI/testing/sysfs-driver-samsung-laptop b/Documentation/ABI/testing/sysfs-driver-samsung-laptop index 0a810231aad..a6a56e11eba 100644 --- a/Documentation/ABI/testing/sysfs-driver-samsung-laptop +++ b/Documentation/ABI/testing/sysfs-driver-samsung-laptop | |||
@@ -17,3 +17,13 @@ Description: Some Samsung laptops have different "performance levels" | |||
17 | Specifically, not all support the "overclock" option, | 17 | Specifically, not all support the "overclock" option, |
18 | and it's still unknown if this value even changes | 18 | and it's still unknown if this value even changes |
19 | anything, other than making the user feel a bit better. | 19 | anything, other than making the user feel a bit better. |
20 | |||
21 | What: /sys/devices/platform/samsung/battery_life_extender | ||
22 | Date: December 1, 2011 | ||
23 | KernelVersion: 3.3 | ||
24 | Contact: Corentin Chary <corentin.chary@gmail.com> | ||
25 | Description: Max battery charge level can be modified, battery cycle | ||
26 | life can be extended by reducing the max battery charge | ||
27 | level. | ||
28 | 0 means normal battery mode (100% charge) | ||
29 | 1 means battery life extender mode (80% charge) | ||
diff --git a/drivers/platform/x86/samsung-laptop.c b/drivers/platform/x86/samsung-laptop.c index b39fa53baa2..918fa358c11 100644 --- a/drivers/platform/x86/samsung-laptop.c +++ b/drivers/platform/x86/samsung-laptop.c | |||
@@ -104,6 +104,10 @@ struct sabi_commands { | |||
104 | u16 get_performance_level; | 104 | u16 get_performance_level; |
105 | u16 set_performance_level; | 105 | u16 set_performance_level; |
106 | 106 | ||
107 | /* 0x80 is off, 0x81 is on */ | ||
108 | u16 get_battery_life_extender; | ||
109 | u16 set_battery_life_extender; | ||
110 | |||
107 | /* | 111 | /* |
108 | * Tell the BIOS that Linux is running on this machine. | 112 | * Tell the BIOS that Linux is running on this machine. |
109 | * 81 is on, 80 is off | 113 | * 81 is on, 80 is off |
@@ -157,6 +161,9 @@ static const struct sabi_config sabi_configs[] = { | |||
157 | .get_performance_level = 0x08, | 161 | .get_performance_level = 0x08, |
158 | .set_performance_level = 0x09, | 162 | .set_performance_level = 0x09, |
159 | 163 | ||
164 | .get_battery_life_extender = 0xFFFF, | ||
165 | .set_battery_life_extender = 0xFFFF, | ||
166 | |||
160 | .set_linux = 0x0a, | 167 | .set_linux = 0x0a, |
161 | }, | 168 | }, |
162 | 169 | ||
@@ -204,6 +211,9 @@ static const struct sabi_config sabi_configs[] = { | |||
204 | .get_performance_level = 0x31, | 211 | .get_performance_level = 0x31, |
205 | .set_performance_level = 0x32, | 212 | .set_performance_level = 0x32, |
206 | 213 | ||
214 | .get_battery_life_extender = 0x65, | ||
215 | .set_battery_life_extender = 0x66, | ||
216 | |||
207 | .set_linux = 0xff, | 217 | .set_linux = 0xff, |
208 | }, | 218 | }, |
209 | 219 | ||
@@ -543,8 +553,78 @@ static ssize_t set_performance_level(struct device *dev, | |||
543 | static DEVICE_ATTR(performance_level, S_IWUSR | S_IRUGO, | 553 | static DEVICE_ATTR(performance_level, S_IWUSR | S_IRUGO, |
544 | get_performance_level, set_performance_level); | 554 | get_performance_level, set_performance_level); |
545 | 555 | ||
556 | static int read_battery_life_extender(struct samsung_laptop *samsung) | ||
557 | { | ||
558 | const struct sabi_commands *commands = &samsung->config->commands; | ||
559 | struct sabi_data data; | ||
560 | int retval; | ||
561 | |||
562 | if (commands->get_battery_life_extender == 0xFFFF) | ||
563 | return -ENODEV; | ||
564 | |||
565 | memset(&data, 0, sizeof(data)); | ||
566 | data.data[0] = 0x80; | ||
567 | retval = sabi_command(samsung, commands->get_battery_life_extender, | ||
568 | &data, &data); | ||
569 | |||
570 | if (retval) | ||
571 | return retval; | ||
572 | |||
573 | if (data.data[0] != 0 && data.data[0] != 1) | ||
574 | return -ENODEV; | ||
575 | |||
576 | return data.data[0]; | ||
577 | } | ||
578 | |||
579 | static int write_battery_life_extender(struct samsung_laptop *samsung, | ||
580 | int enabled) | ||
581 | { | ||
582 | const struct sabi_commands *commands = &samsung->config->commands; | ||
583 | struct sabi_data data; | ||
584 | |||
585 | memset(&data, 0, sizeof(data)); | ||
586 | data.data[0] = 0x80 | enabled; | ||
587 | return sabi_command(samsung, commands->set_battery_life_extender, | ||
588 | &data, NULL); | ||
589 | } | ||
590 | |||
591 | static ssize_t get_battery_life_extender(struct device *dev, | ||
592 | struct device_attribute *attr, | ||
593 | char *buf) | ||
594 | { | ||
595 | struct samsung_laptop *samsung = dev_get_drvdata(dev); | ||
596 | int ret; | ||
597 | |||
598 | ret = read_battery_life_extender(samsung); | ||
599 | if (ret < 0) | ||
600 | return ret; | ||
601 | |||
602 | return sprintf(buf, "%d\n", ret); | ||
603 | } | ||
604 | |||
605 | static ssize_t set_battery_life_extender(struct device *dev, | ||
606 | struct device_attribute *attr, | ||
607 | const char *buf, size_t count) | ||
608 | { | ||
609 | struct samsung_laptop *samsung = dev_get_drvdata(dev); | ||
610 | int ret, value; | ||
611 | |||
612 | if (!count || sscanf(buf, "%i", &value) != 1) | ||
613 | return -EINVAL; | ||
614 | |||
615 | ret = write_battery_life_extender(samsung, !!value); | ||
616 | if (ret < 0) | ||
617 | return ret; | ||
618 | |||
619 | return count; | ||
620 | } | ||
621 | |||
622 | static DEVICE_ATTR(battery_life_extender, S_IWUSR | S_IRUGO, | ||
623 | get_battery_life_extender, set_battery_life_extender); | ||
624 | |||
546 | static struct attribute *platform_attributes[] = { | 625 | static struct attribute *platform_attributes[] = { |
547 | &dev_attr_performance_level.attr, | 626 | &dev_attr_performance_level.attr, |
627 | &dev_attr_battery_life_extender.attr, | ||
548 | NULL | 628 | NULL |
549 | }; | 629 | }; |
550 | 630 | ||
@@ -643,6 +723,8 @@ static mode_t samsung_sysfs_is_visible(struct kobject *kobj, | |||
643 | 723 | ||
644 | if (attr == &dev_attr_performance_level.attr) | 724 | if (attr == &dev_attr_performance_level.attr) |
645 | ok = !!samsung->config->performance_levels[0].name; | 725 | ok = !!samsung->config->performance_levels[0].name; |
726 | if (attr == &dev_attr_battery_life_extender.attr) | ||
727 | ok = !!(read_battery_life_extender(samsung) >= 0); | ||
646 | 728 | ||
647 | return ok ? attr->mode : 0; | 729 | return ok ? attr->mode : 0; |
648 | } | 730 | } |