@@ -9214,6 +9214,8 @@ static struct ibm_struct mute_led_driver_data = {
9214
9214
#define SET_START "BCCS"
9215
9215
#define GET_STOP "BCSG"
9216
9216
#define SET_STOP "BCSS"
9217
+ #define GET_DISCHARGE "BDSG"
9218
+ #define SET_DISCHARGE "BDSS"
9217
9219
9218
9220
enum {
9219
9221
BAT_ANY = 0 ,
@@ -9230,13 +9232,15 @@ enum {
9230
9232
/* This is used in the get/set helpers */
9231
9233
THRESHOLD_START ,
9232
9234
THRESHOLD_STOP ,
9235
+ FORCE_DISCHARGE ,
9233
9236
};
9234
9237
9235
9238
struct tpacpi_battery_data {
9236
9239
int charge_start ;
9237
9240
int start_support ;
9238
9241
int charge_stop ;
9239
9242
int stop_support ;
9243
+ unsigned int charge_behaviours ;
9240
9244
};
9241
9245
9242
9246
struct tpacpi_battery_driver_data {
@@ -9294,6 +9298,12 @@ static int tpacpi_battery_get(int what, int battery, int *ret)
9294
9298
if (* ret == 0 )
9295
9299
* ret = 100 ;
9296
9300
return 0 ;
9301
+ case FORCE_DISCHARGE :
9302
+ if ACPI_FAILURE (tpacpi_battery_acpi_eval (GET_DISCHARGE , ret , battery ))
9303
+ return - ENODEV ;
9304
+ /* The force discharge status is in bit 0 */
9305
+ * ret = * ret & 0x01 ;
9306
+ return 0 ;
9297
9307
default :
9298
9308
pr_crit ("wrong parameter: %d" , what );
9299
9309
return - EINVAL ;
@@ -9322,12 +9332,49 @@ static int tpacpi_battery_set(int what, int battery, int value)
9322
9332
return - ENODEV ;
9323
9333
}
9324
9334
return 0 ;
9335
+ case FORCE_DISCHARGE :
9336
+ /* Force discharge is in bit 0,
9337
+ * break on AC attach is in bit 1 (won't work on some ThinkPads),
9338
+ * battery ID is in bits 8-9, 2 bits.
9339
+ */
9340
+ if (ACPI_FAILURE (tpacpi_battery_acpi_eval (SET_DISCHARGE , & ret , param ))) {
9341
+ pr_err ("failed to set force discharge on %d" , battery );
9342
+ return - ENODEV ;
9343
+ }
9344
+ return 0 ;
9325
9345
default :
9326
9346
pr_crit ("wrong parameter: %d" , what );
9327
9347
return - EINVAL ;
9328
9348
}
9329
9349
}
9330
9350
9351
+ static int tpacpi_battery_set_validate (int what , int battery , int value )
9352
+ {
9353
+ int ret , v ;
9354
+
9355
+ ret = tpacpi_battery_set (what , battery , value );
9356
+ if (ret < 0 )
9357
+ return ret ;
9358
+
9359
+ ret = tpacpi_battery_get (what , battery , & v );
9360
+ if (ret < 0 )
9361
+ return ret ;
9362
+
9363
+ if (v == value )
9364
+ return 0 ;
9365
+
9366
+ msleep (500 );
9367
+
9368
+ ret = tpacpi_battery_get (what , battery , & v );
9369
+ if (ret < 0 )
9370
+ return ret ;
9371
+
9372
+ if (v == value )
9373
+ return 0 ;
9374
+
9375
+ return - EIO ;
9376
+ }
9377
+
9331
9378
static int tpacpi_battery_probe (int battery )
9332
9379
{
9333
9380
int ret = 0 ;
@@ -9340,6 +9387,8 @@ static int tpacpi_battery_probe(int battery)
9340
9387
* 2) Check for support
9341
9388
* 3) Get the current stop threshold
9342
9389
* 4) Check for support
9390
+ * 5) Get the current force discharge status
9391
+ * 6) Check for support
9343
9392
*/
9344
9393
if (acpi_has_method (hkey_handle , GET_START )) {
9345
9394
if ACPI_FAILURE (tpacpi_battery_acpi_eval (GET_START , & ret , battery )) {
@@ -9376,10 +9425,25 @@ static int tpacpi_battery_probe(int battery)
9376
9425
return - ENODEV ;
9377
9426
}
9378
9427
}
9379
- pr_info ("battery %d registered (start %d, stop %d)" ,
9380
- battery ,
9381
- battery_info .batteries [battery ].charge_start ,
9382
- battery_info .batteries [battery ].charge_stop );
9428
+ if (acpi_has_method (hkey_handle , GET_DISCHARGE )) {
9429
+ if (ACPI_FAILURE (tpacpi_battery_acpi_eval (GET_DISCHARGE , & ret , battery ))) {
9430
+ pr_err ("Error probing battery discharge; %d\n" , battery );
9431
+ return - ENODEV ;
9432
+ }
9433
+ /* Support is marked in bit 8 */
9434
+ if (ret & BIT (8 ))
9435
+ battery_info .batteries [battery ].charge_behaviours |=
9436
+ BIT (POWER_SUPPLY_CHARGE_BEHAVIOUR_FORCE_DISCHARGE );
9437
+ }
9438
+
9439
+ battery_info .batteries [battery ].charge_behaviours |=
9440
+ BIT (POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO );
9441
+
9442
+ pr_info ("battery %d registered (start %d, stop %d, behaviours: 0x%x)\n" ,
9443
+ battery ,
9444
+ battery_info .batteries [battery ].charge_start ,
9445
+ battery_info .batteries [battery ].charge_stop ,
9446
+ battery_info .batteries [battery ].charge_behaviours );
9383
9447
9384
9448
return 0 ;
9385
9449
}
@@ -9514,6 +9578,28 @@ static ssize_t charge_control_end_threshold_show(struct device *device,
9514
9578
return tpacpi_battery_show (THRESHOLD_STOP , device , buf );
9515
9579
}
9516
9580
9581
+ static ssize_t charge_behaviour_show (struct device * dev ,
9582
+ struct device_attribute * attr ,
9583
+ char * buf )
9584
+ {
9585
+ enum power_supply_charge_behaviour active = POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO ;
9586
+ struct power_supply * supply = to_power_supply (dev );
9587
+ unsigned int available ;
9588
+ int ret , battery ;
9589
+
9590
+ battery = tpacpi_battery_get_id (supply -> desc -> name );
9591
+ available = battery_info .batteries [battery ].charge_behaviours ;
9592
+
9593
+ if (available & BIT (POWER_SUPPLY_CHARGE_BEHAVIOUR_FORCE_DISCHARGE )) {
9594
+ if (tpacpi_battery_get (FORCE_DISCHARGE , battery , & ret ))
9595
+ return - ENODEV ;
9596
+ if (ret )
9597
+ active = POWER_SUPPLY_CHARGE_BEHAVIOUR_FORCE_DISCHARGE ;
9598
+ }
9599
+
9600
+ return power_supply_charge_behaviour_show (dev , available , active , buf );
9601
+ }
9602
+
9517
9603
static ssize_t charge_control_start_threshold_store (struct device * dev ,
9518
9604
struct device_attribute * attr ,
9519
9605
const char * buf , size_t count )
@@ -9528,8 +9614,44 @@ static ssize_t charge_control_end_threshold_store(struct device *dev,
9528
9614
return tpacpi_battery_store (THRESHOLD_STOP , dev , buf , count );
9529
9615
}
9530
9616
9617
+ static ssize_t charge_behaviour_store (struct device * dev ,
9618
+ struct device_attribute * attr ,
9619
+ const char * buf , size_t count )
9620
+ {
9621
+ struct power_supply * supply = to_power_supply (dev );
9622
+ int selected , battery , ret = 0 ;
9623
+ unsigned int available ;
9624
+
9625
+ battery = tpacpi_battery_get_id (supply -> desc -> name );
9626
+ available = battery_info .batteries [battery ].charge_behaviours ;
9627
+ selected = power_supply_charge_behaviour_parse (available , buf );
9628
+
9629
+ if (selected < 0 )
9630
+ return selected ;
9631
+
9632
+ switch (selected ) {
9633
+ case POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO :
9634
+ if (available & BIT (POWER_SUPPLY_CHARGE_BEHAVIOUR_FORCE_DISCHARGE ))
9635
+ ret = tpacpi_battery_set_validate (FORCE_DISCHARGE , battery , 0 );
9636
+ if (ret < 0 )
9637
+ return ret ;
9638
+ break ;
9639
+ case POWER_SUPPLY_CHARGE_BEHAVIOUR_FORCE_DISCHARGE :
9640
+ ret = tpacpi_battery_set_validate (FORCE_DISCHARGE , battery , 1 );
9641
+ if (ret < 0 )
9642
+ return ret ;
9643
+ break ;
9644
+ default :
9645
+ dev_err (dev , "Unexpected charge behaviour: %d\n" , selected );
9646
+ return - EINVAL ;
9647
+ }
9648
+
9649
+ return count ;
9650
+ }
9651
+
9531
9652
static DEVICE_ATTR_RW (charge_control_start_threshold );
9532
9653
static DEVICE_ATTR_RW (charge_control_end_threshold );
9654
+ static DEVICE_ATTR_RW (charge_behaviour );
9533
9655
static struct device_attribute dev_attr_charge_start_threshold = __ATTR (
9534
9656
charge_start_threshold ,
9535
9657
0644 ,
@@ -9548,6 +9670,7 @@ static struct attribute *tpacpi_battery_attrs[] = {
9548
9670
& dev_attr_charge_control_end_threshold .attr ,
9549
9671
& dev_attr_charge_start_threshold .attr ,
9550
9672
& dev_attr_charge_stop_threshold .attr ,
9673
+ & dev_attr_charge_behaviour .attr ,
9551
9674
NULL ,
9552
9675
};
9553
9676
0 commit comments