]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
platform/x86: samsung-laptop: Expose charge_types
authorJelle van der Waa <jvanderwaa@redhat.com>
Wed, 2 Jul 2025 18:28:43 +0000 (20:28 +0200)
committerIlpo Järvinen <ilpo.jarvinen@linux.intel.com>
Tue, 22 Jul 2025 14:38:39 +0000 (17:38 +0300)
Support the newly introduced charge_types sysfs attribute as a
replacement for the custom `battery_life_extender` attribute. Setting
charge_types to `Long Life` enables battery life extending mode.

This change is similar to the recent Ideapad patch adding support for
charge_types.

Signed-off-by: Jelle van der Waa <jvanderwaa@redhat.com>
Link: https://lore.kernel.org/r/20250702182844.107706-1-jvanderwaa@redhat.com
Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Documentation/ABI/obsolete/sysfs-driver-samsung-laptop [new file with mode: 0644]
Documentation/ABI/testing/sysfs-driver-samsung-laptop
drivers/platform/x86/Kconfig
drivers/platform/x86/samsung-laptop.c

diff --git a/Documentation/ABI/obsolete/sysfs-driver-samsung-laptop b/Documentation/ABI/obsolete/sysfs-driver-samsung-laptop
new file mode 100644 (file)
index 0000000..204c3f3
--- /dev/null
@@ -0,0 +1,10 @@
+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)
index 28c9c040de5d15956b35771550caec97bf1c033b..408cb0ddf4aa1fce6ad8cd70611794b1ef670d76 100644 (file)
@@ -20,17 +20,6 @@ Description: Some Samsung laptops have different "performance levels"
                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@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)
-
 What:          /sys/devices/platform/samsung/usb_charge
 Date:          December 1, 2011
 KernelVersion: 3.3
index 49ca98df47fd861478295970e056f6c9feb361b7..6d238e120dce78ce5462d442e612e5318b6f28a5 100644 (file)
@@ -619,6 +619,7 @@ config SAMSUNG_LAPTOP
        tristate "Samsung Laptop driver"
        depends on RFKILL || RFKILL = n
        depends on ACPI_VIDEO || ACPI_VIDEO = n
+       depends on ACPI_BATTERY
        depends on BACKLIGHT_CLASS_DEVICE
        select LEDS_CLASS
        select NEW_LEDS
index decde4c9a3d97695e17694472f5b6abceadb8285..9d43a12db73c8f4c7283971c9b85a8b18c29cb1c 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/leds.h>
 #include <linux/dmi.h>
 #include <linux/platform_device.h>
+#include <linux/power_supply.h>
 #include <linux/rfkill.h>
 #include <linux/acpi.h>
 #include <linux/seq_file.h>
@@ -23,6 +24,7 @@
 #include <linux/ctype.h>
 #include <linux/efi.h>
 #include <linux/suspend.h>
+#include <acpi/battery.h>
 #include <acpi/video.h>
 
 /*
@@ -348,6 +350,8 @@ struct samsung_laptop {
 
        struct notifier_block pm_nb;
 
+       struct acpi_battery_hook battery_hook;
+
        bool handle_backlight;
        bool has_stepping_quirk;
 
@@ -697,6 +701,11 @@ static ssize_t set_performance_level(struct device *dev,
 static DEVICE_ATTR(performance_level, 0644,
                   get_performance_level, set_performance_level);
 
+static void show_battery_life_extender_deprecation_warning(struct device *dev)
+{
+       dev_warn_once(dev, "battery_life_extender attribute has been deprecated, see charge_types.\n");
+}
+
 static int read_battery_life_extender(struct samsung_laptop *samsung)
 {
        const struct sabi_commands *commands = &samsung->config->commands;
@@ -739,6 +748,8 @@ static ssize_t get_battery_life_extender(struct device *dev,
        struct samsung_laptop *samsung = dev_get_drvdata(dev);
        int ret;
 
+       show_battery_life_extender_deprecation_warning(dev);
+
        ret = read_battery_life_extender(samsung);
        if (ret < 0)
                return ret;
@@ -753,6 +764,8 @@ static ssize_t set_battery_life_extender(struct device *dev,
        struct samsung_laptop *samsung = dev_get_drvdata(dev);
        int ret, value;
 
+       show_battery_life_extender_deprecation_warning(dev);
+
        if (!count || kstrtoint(buf, 0, &value) != 0)
                return -EINVAL;
 
@@ -766,6 +779,84 @@ static ssize_t set_battery_life_extender(struct device *dev,
 static DEVICE_ATTR(battery_life_extender, 0644,
                   get_battery_life_extender, set_battery_life_extender);
 
+static int samsung_psy_ext_set_prop(struct power_supply *psy,
+                                   const struct power_supply_ext *ext,
+                                   void *ext_data,
+                                   enum power_supply_property psp,
+                                   const union power_supply_propval *val)
+{
+       struct samsung_laptop *samsung = ext_data;
+
+       switch (val->intval) {
+       case POWER_SUPPLY_CHARGE_TYPE_LONGLIFE:
+               return write_battery_life_extender(samsung, 1);
+       case POWER_SUPPLY_CHARGE_TYPE_STANDARD:
+               return write_battery_life_extender(samsung, 0);
+       default:
+               return -EINVAL;
+       }
+}
+
+static int samsung_psy_ext_get_prop(struct power_supply *psy,
+                                   const struct power_supply_ext *ext,
+                                   void *ext_data,
+                                   enum power_supply_property psp,
+                                   union power_supply_propval *val)
+{
+       struct samsung_laptop *samsung = ext_data;
+       int ret;
+
+       ret = read_battery_life_extender(samsung);
+       if (ret < 0)
+               return ret;
+
+       if (ret == 1)
+               val->intval = POWER_SUPPLY_CHARGE_TYPE_LONGLIFE;
+       else
+               val->intval = POWER_SUPPLY_CHARGE_TYPE_STANDARD;
+
+       return 0;
+}
+
+static int samsung_psy_prop_is_writeable(struct power_supply *psy,
+                                        const struct power_supply_ext *ext,
+                                        void *data,
+                                        enum power_supply_property psp)
+{
+       return true;
+}
+
+static const enum power_supply_property samsung_power_supply_props[] = {
+       POWER_SUPPLY_PROP_CHARGE_TYPES,
+};
+
+static const struct power_supply_ext samsung_battery_ext = {
+       .name                   = "samsung_laptop",
+       .properties             = samsung_power_supply_props,
+       .num_properties         = ARRAY_SIZE(samsung_power_supply_props),
+       .charge_types           = (BIT(POWER_SUPPLY_CHARGE_TYPE_STANDARD) |
+                                  BIT(POWER_SUPPLY_CHARGE_TYPE_LONGLIFE)),
+       .get_property           = samsung_psy_ext_get_prop,
+       .set_property           = samsung_psy_ext_set_prop,
+       .property_is_writeable  = samsung_psy_prop_is_writeable,
+};
+
+static int samsung_battery_add(struct power_supply *battery, struct acpi_battery_hook *hook)
+{
+       struct samsung_laptop *samsung = container_of(hook, struct samsung_laptop, battery_hook);
+
+       return power_supply_register_extension(battery, &samsung_battery_ext,
+                                              &samsung->platform_device->dev, samsung);
+}
+
+static int samsung_battery_remove(struct power_supply *battery,
+                                 struct acpi_battery_hook *hook)
+{
+       power_supply_unregister_extension(battery, &samsung_battery_ext);
+
+       return 0;
+}
+
 static int read_usb_charge(struct samsung_laptop *samsung)
 {
        const struct sabi_commands *commands = &samsung->config->commands;
@@ -1043,6 +1134,21 @@ static int __init samsung_lid_handling_init(struct samsung_laptop *samsung)
        return retval;
 }
 
+static int __init samsung_battery_hook_init(struct samsung_laptop *samsung)
+{
+       int retval = 0;
+
+       if (samsung->config->commands.get_battery_life_extender != 0xFFFF) {
+               samsung->battery_hook.add_battery = samsung_battery_add;
+               samsung->battery_hook.remove_battery = samsung_battery_remove;
+               samsung->battery_hook.name = "Samsung Battery Extension";
+               retval = devm_battery_hook_register(&samsung->platform_device->dev,
+                                                   &samsung->battery_hook);
+       }
+
+       return retval;
+}
+
 static int kbd_backlight_enable(struct samsung_laptop *samsung)
 {
        const struct sabi_commands *commands = &samsung->config->commands;
@@ -1604,6 +1710,10 @@ static int __init samsung_init(void)
        if (ret)
                goto error_lid_handling;
 
+       ret = samsung_battery_hook_init(samsung);
+       if (ret)
+               goto error_lid_handling;
+
        samsung_debugfs_init(samsung);
 
        samsung->pm_nb.notifier_call = samsung_pm_notification;