aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/ABI/testing/sysfs-driver-samsung-laptop10
-rw-r--r--drivers/platform/x86/samsung-laptop.c82
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
21What: /sys/devices/platform/samsung/battery_life_extender
22Date: December 1, 2011
23KernelVersion: 3.3
24Contact: Corentin Chary <corentin.chary@gmail.com>
25Description: 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,
543static DEVICE_ATTR(performance_level, S_IWUSR | S_IRUGO, 553static DEVICE_ATTR(performance_level, S_IWUSR | S_IRUGO,
544 get_performance_level, set_performance_level); 554 get_performance_level, set_performance_level);
545 555
556static 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
579static 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
591static 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
605static 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
622static DEVICE_ATTR(battery_life_extender, S_IWUSR | S_IRUGO,
623 get_battery_life_extender, set_battery_life_extender);
624
546static struct attribute *platform_attributes[] = { 625static 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}