1616#include <linux/leds.h>
1717#include <linux/dmi.h>
1818#include <linux/platform_device.h>
19+ #include <linux/power_supply.h>
1920#include <linux/rfkill.h>
2021#include <linux/acpi.h>
2122#include <linux/seq_file.h>
2223#include <linux/debugfs.h>
2324#include <linux/ctype.h>
2425#include <linux/efi.h>
2526#include <linux/suspend.h>
27+ #include <acpi/battery.h>
2628#include <acpi/video.h>
2729
2830/*
@@ -348,6 +350,8 @@ struct samsung_laptop {
348350
349351 struct notifier_block pm_nb ;
350352
353+ struct acpi_battery_hook battery_hook ;
354+
351355 bool handle_backlight ;
352356 bool has_stepping_quirk ;
353357
@@ -697,6 +701,11 @@ static ssize_t set_performance_level(struct device *dev,
697701static DEVICE_ATTR (performance_level , 0644 ,
698702 get_performance_level , set_performance_level ) ;
699703
704+ static void show_battery_life_extender_deprecation_warning (struct device * dev )
705+ {
706+ dev_warn_once (dev , "battery_life_extender attribute has been deprecated, see charge_types.\n" );
707+ }
708+
700709static int read_battery_life_extender (struct samsung_laptop * samsung )
701710{
702711 const struct sabi_commands * commands = & samsung -> config -> commands ;
@@ -739,6 +748,8 @@ static ssize_t get_battery_life_extender(struct device *dev,
739748 struct samsung_laptop * samsung = dev_get_drvdata (dev );
740749 int ret ;
741750
751+ show_battery_life_extender_deprecation_warning (dev );
752+
742753 ret = read_battery_life_extender (samsung );
743754 if (ret < 0 )
744755 return ret ;
@@ -753,6 +764,8 @@ static ssize_t set_battery_life_extender(struct device *dev,
753764 struct samsung_laptop * samsung = dev_get_drvdata (dev );
754765 int ret , value ;
755766
767+ show_battery_life_extender_deprecation_warning (dev );
768+
756769 if (!count || kstrtoint (buf , 0 , & value ) != 0 )
757770 return - EINVAL ;
758771
@@ -766,6 +779,84 @@ static ssize_t set_battery_life_extender(struct device *dev,
766779static DEVICE_ATTR (battery_life_extender , 0644 ,
767780 get_battery_life_extender , set_battery_life_extender ) ;
768781
782+ static int samsung_psy_ext_set_prop (struct power_supply * psy ,
783+ const struct power_supply_ext * ext ,
784+ void * ext_data ,
785+ enum power_supply_property psp ,
786+ const union power_supply_propval * val )
787+ {
788+ struct samsung_laptop * samsung = ext_data ;
789+
790+ switch (val -> intval ) {
791+ case POWER_SUPPLY_CHARGE_TYPE_LONGLIFE :
792+ return write_battery_life_extender (samsung , 1 );
793+ case POWER_SUPPLY_CHARGE_TYPE_STANDARD :
794+ return write_battery_life_extender (samsung , 0 );
795+ default :
796+ return - EINVAL ;
797+ }
798+ }
799+
800+ static int samsung_psy_ext_get_prop (struct power_supply * psy ,
801+ const struct power_supply_ext * ext ,
802+ void * ext_data ,
803+ enum power_supply_property psp ,
804+ union power_supply_propval * val )
805+ {
806+ struct samsung_laptop * samsung = ext_data ;
807+ int ret ;
808+
809+ ret = read_battery_life_extender (samsung );
810+ if (ret < 0 )
811+ return ret ;
812+
813+ if (ret == 1 )
814+ val -> intval = POWER_SUPPLY_CHARGE_TYPE_LONGLIFE ;
815+ else
816+ val -> intval = POWER_SUPPLY_CHARGE_TYPE_STANDARD ;
817+
818+ return 0 ;
819+ }
820+
821+ static int samsung_psy_prop_is_writeable (struct power_supply * psy ,
822+ const struct power_supply_ext * ext ,
823+ void * data ,
824+ enum power_supply_property psp )
825+ {
826+ return true;
827+ }
828+
829+ static const enum power_supply_property samsung_power_supply_props [] = {
830+ POWER_SUPPLY_PROP_CHARGE_TYPES ,
831+ };
832+
833+ static const struct power_supply_ext samsung_battery_ext = {
834+ .name = "samsung_laptop" ,
835+ .properties = samsung_power_supply_props ,
836+ .num_properties = ARRAY_SIZE (samsung_power_supply_props ),
837+ .charge_types = (BIT (POWER_SUPPLY_CHARGE_TYPE_STANDARD ) |
838+ BIT (POWER_SUPPLY_CHARGE_TYPE_LONGLIFE )),
839+ .get_property = samsung_psy_ext_get_prop ,
840+ .set_property = samsung_psy_ext_set_prop ,
841+ .property_is_writeable = samsung_psy_prop_is_writeable ,
842+ };
843+
844+ static int samsung_battery_add (struct power_supply * battery , struct acpi_battery_hook * hook )
845+ {
846+ struct samsung_laptop * samsung = container_of (hook , struct samsung_laptop , battery_hook );
847+
848+ return power_supply_register_extension (battery , & samsung_battery_ext ,
849+ & samsung -> platform_device -> dev , samsung );
850+ }
851+
852+ static int samsung_battery_remove (struct power_supply * battery ,
853+ struct acpi_battery_hook * hook )
854+ {
855+ power_supply_unregister_extension (battery , & samsung_battery_ext );
856+
857+ return 0 ;
858+ }
859+
769860static int read_usb_charge (struct samsung_laptop * samsung )
770861{
771862 const struct sabi_commands * commands = & samsung -> config -> commands ;
@@ -1043,6 +1134,21 @@ static int __init samsung_lid_handling_init(struct samsung_laptop *samsung)
10431134 return retval ;
10441135}
10451136
1137+ static int __init samsung_battery_hook_init (struct samsung_laptop * samsung )
1138+ {
1139+ int retval = 0 ;
1140+
1141+ if (samsung -> config -> commands .get_battery_life_extender != 0xFFFF ) {
1142+ samsung -> battery_hook .add_battery = samsung_battery_add ;
1143+ samsung -> battery_hook .remove_battery = samsung_battery_remove ;
1144+ samsung -> battery_hook .name = "Samsung Battery Extension" ;
1145+ retval = devm_battery_hook_register (& samsung -> platform_device -> dev ,
1146+ & samsung -> battery_hook );
1147+ }
1148+
1149+ return retval ;
1150+ }
1151+
10461152static int kbd_backlight_enable (struct samsung_laptop * samsung )
10471153{
10481154 const struct sabi_commands * commands = & samsung -> config -> commands ;
@@ -1604,6 +1710,10 @@ static int __init samsung_init(void)
16041710 if (ret )
16051711 goto error_lid_handling ;
16061712
1713+ ret = samsung_battery_hook_init (samsung );
1714+ if (ret )
1715+ goto error_lid_handling ;
1716+
16071717 samsung_debugfs_init (samsung );
16081718
16091719 samsung -> pm_nb .notifier_call = samsung_pm_notification ;
0 commit comments