Commit cb5b5c91 authored by Corentin Chary's avatar Corentin Chary Committed by Matthew Garrett

samsung-laptop: add battery life extender support

Signed-off-by: default avatarCorentin Chary <corentincj@iksaif.net>
Acked-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
Signed-off-by: default avatarMatthew Garrett <mjg@redhat.com>
parent 49dd7730
...@@ -17,3 +17,13 @@ Description: Some Samsung laptops have different "performance levels" ...@@ -17,3 +17,13 @@ Description: Some Samsung laptops have different "performance levels"
Specifically, not all support the "overclock" option, Specifically, not all support the "overclock" option,
and it's still unknown if this value even changes and it's still unknown if this value even changes
anything, other than making the user feel a bit better. anything, other than making the user feel a bit better.
What: /sys/devices/platform/samsung/battery_life_extender
Date: December 1, 2011
KernelVersion: 3.3
Contact: Corentin Chary <corentin.chary@gmail.com>
Description: Max battery charge level can be modified, battery cycle
life can be extended by reducing the max battery charge
level.
0 means normal battery mode (100% charge)
1 means battery life extender mode (80% charge)
...@@ -104,6 +104,10 @@ struct sabi_commands { ...@@ -104,6 +104,10 @@ struct sabi_commands {
u16 get_performance_level; u16 get_performance_level;
u16 set_performance_level; u16 set_performance_level;
/* 0x80 is off, 0x81 is on */
u16 get_battery_life_extender;
u16 set_battery_life_extender;
/* /*
* Tell the BIOS that Linux is running on this machine. * Tell the BIOS that Linux is running on this machine.
* 81 is on, 80 is off * 81 is on, 80 is off
...@@ -157,6 +161,9 @@ static const struct sabi_config sabi_configs[] = { ...@@ -157,6 +161,9 @@ static const struct sabi_config sabi_configs[] = {
.get_performance_level = 0x08, .get_performance_level = 0x08,
.set_performance_level = 0x09, .set_performance_level = 0x09,
.get_battery_life_extender = 0xFFFF,
.set_battery_life_extender = 0xFFFF,
.set_linux = 0x0a, .set_linux = 0x0a,
}, },
...@@ -204,6 +211,9 @@ static const struct sabi_config sabi_configs[] = { ...@@ -204,6 +211,9 @@ static const struct sabi_config sabi_configs[] = {
.get_performance_level = 0x31, .get_performance_level = 0x31,
.set_performance_level = 0x32, .set_performance_level = 0x32,
.get_battery_life_extender = 0x65,
.set_battery_life_extender = 0x66,
.set_linux = 0xff, .set_linux = 0xff,
}, },
...@@ -543,8 +553,78 @@ static ssize_t set_performance_level(struct device *dev, ...@@ -543,8 +553,78 @@ static ssize_t set_performance_level(struct device *dev,
static DEVICE_ATTR(performance_level, S_IWUSR | S_IRUGO, static DEVICE_ATTR(performance_level, S_IWUSR | S_IRUGO,
get_performance_level, set_performance_level); get_performance_level, set_performance_level);
static int read_battery_life_extender(struct samsung_laptop *samsung)
{
const struct sabi_commands *commands = &samsung->config->commands;
struct sabi_data data;
int retval;
if (commands->get_battery_life_extender == 0xFFFF)
return -ENODEV;
memset(&data, 0, sizeof(data));
data.data[0] = 0x80;
retval = sabi_command(samsung, commands->get_battery_life_extender,
&data, &data);
if (retval)
return retval;
if (data.data[0] != 0 && data.data[0] != 1)
return -ENODEV;
return data.data[0];
}
static int write_battery_life_extender(struct samsung_laptop *samsung,
int enabled)
{
const struct sabi_commands *commands = &samsung->config->commands;
struct sabi_data data;
memset(&data, 0, sizeof(data));
data.data[0] = 0x80 | enabled;
return sabi_command(samsung, commands->set_battery_life_extender,
&data, NULL);
}
static ssize_t get_battery_life_extender(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct samsung_laptop *samsung = dev_get_drvdata(dev);
int ret;
ret = read_battery_life_extender(samsung);
if (ret < 0)
return ret;
return sprintf(buf, "%d\n", ret);
}
static ssize_t set_battery_life_extender(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct samsung_laptop *samsung = dev_get_drvdata(dev);
int ret, value;
if (!count || sscanf(buf, "%i", &value) != 1)
return -EINVAL;
ret = write_battery_life_extender(samsung, !!value);
if (ret < 0)
return ret;
return count;
}
static DEVICE_ATTR(battery_life_extender, S_IWUSR | S_IRUGO,
get_battery_life_extender, set_battery_life_extender);
static struct attribute *platform_attributes[] = { static struct attribute *platform_attributes[] = {
&dev_attr_performance_level.attr, &dev_attr_performance_level.attr,
&dev_attr_battery_life_extender.attr,
NULL NULL
}; };
...@@ -643,6 +723,8 @@ static mode_t samsung_sysfs_is_visible(struct kobject *kobj, ...@@ -643,6 +723,8 @@ static mode_t samsung_sysfs_is_visible(struct kobject *kobj,
if (attr == &dev_attr_performance_level.attr) if (attr == &dev_attr_performance_level.attr)
ok = !!samsung->config->performance_levels[0].name; ok = !!samsung->config->performance_levels[0].name;
if (attr == &dev_attr_battery_life_extender.attr)
ok = !!(read_battery_life_extender(samsung) >= 0);
return ok ? attr->mode : 0; return ok ? attr->mode : 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment