Re: [PATCH 08/15] samsung-laptop: add battery life extender support
From: David Herrmann
Date: Wed Nov 23 2011 - 11:17:53 EST
Hi Corentin
On Tue, Nov 22, 2011 at 11:02 PM, Corentin Chary <corentincj@xxxxxxxxxx> wrote:
> Signed-off-by: Corentin Chary <corentincj@xxxxxxxxxx>
> ---
> .../ABI/testing/sysfs-driver-samsung-laptop | 10 +++
> 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 0a81023..a6a56e1 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"
> Specifically, not all support the "overclock" option,
> and it's still unknown if this value even changes
> 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@xxxxxxxxx>
> +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)
> diff --git a/drivers/platform/x86/samsung-laptop.c b/drivers/platform/x86/samsung-laptop.c
> index 6493542..16f45da 100644
> --- a/drivers/platform/x86/samsung-laptop.c
> +++ b/drivers/platform/x86/samsung-laptop.c
> @@ -104,6 +104,10 @@ struct sabi_commands {
> u16 get_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.
> * 81 is on, 80 is off
> @@ -157,6 +161,9 @@ static const struct sabi_config sabi_configs[] = {
> .get_performance_level = 0x08,
> .set_performance_level = 0x09,
>
> + .get_battery_life_extender = 0xFFFF,
> + .set_battery_life_extender = 0xFFFF,
> +
> .set_linux = 0x0a,
> },
>
> @@ -204,6 +211,9 @@ static const struct sabi_config sabi_configs[] = {
> .get_performance_level = 0x31,
> .set_performance_level = 0x32,
>
> + .get_battery_life_extender = 0x65,
> + .set_battery_life_extender = 0x66,
> +
> .set_linux = 0xff,
> },
>
> @@ -531,8 +541,78 @@ static ssize_t set_performance_level(struct device *dev,
> static DEVICE_ATTR(performance_level, S_IWUSR | S_IRUGO,
> 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[] = {
> &dev_attr_performance_level.attr,
> + &dev_attr_battery_life_extender.attr,
> NULL
> };
>
> @@ -631,6 +711,8 @@ static mode_t samsung_sysfs_is_visible(struct kobject *kobj,
>
> if (attr == &dev_attr_performance_level.attr)
> 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;
> }
> --
> 1.7.5.4
My BIOS provides this option, too. However, this driver does not
detect it on my machine. During initialization I get:
samsung_laptop: SABI command 0x0078 failed with completion flag 0xaa
Maybe you can help debugging this. If there is something I can test
via debugfs, just tell me.
Regards
David
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/