diff options
-rw-r--r-- | drivers/acpi/battery.c | 68 |
1 files changed, 58 insertions, 10 deletions
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index b2b48f8545c7..1ca0ea77115b 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c | |||
@@ -54,6 +54,7 @@ | |||
54 | #define ACPI_BATTERY_DEVICE_NAME "Battery" | 54 | #define ACPI_BATTERY_DEVICE_NAME "Battery" |
55 | #define ACPI_BATTERY_NOTIFY_STATUS 0x80 | 55 | #define ACPI_BATTERY_NOTIFY_STATUS 0x80 |
56 | #define ACPI_BATTERY_NOTIFY_INFO 0x81 | 56 | #define ACPI_BATTERY_NOTIFY_INFO 0x81 |
57 | #define ACPI_BATTERY_NOTIFY_THRESHOLD 0x82 | ||
57 | 58 | ||
58 | #define _COMPONENT ACPI_BATTERY_COMPONENT | 59 | #define _COMPONENT ACPI_BATTERY_COMPONENT |
59 | 60 | ||
@@ -90,9 +91,11 @@ MODULE_DEVICE_TABLE(acpi, battery_device_ids); | |||
90 | 91 | ||
91 | enum { | 92 | enum { |
92 | ACPI_BATTERY_ALARM_PRESENT, | 93 | ACPI_BATTERY_ALARM_PRESENT, |
93 | /* For buggy DSDTs that report negative 16-bit values for either charging | 94 | ACPI_BATTERY_XINFO_PRESENT, |
94 | * or discharging current and/or report 0 as 65536 due to bad math. | 95 | /* For buggy DSDTs that report negative 16-bit values for either |
95 | */ | 96 | * charging or discharging current and/or report 0 as 65536 |
97 | * due to bad math. | ||
98 | */ | ||
96 | ACPI_BATTERY_QUIRK_SIGNED16_CURRENT, | 99 | ACPI_BATTERY_QUIRK_SIGNED16_CURRENT, |
97 | }; | 100 | }; |
98 | 101 | ||
@@ -112,6 +115,12 @@ struct acpi_battery { | |||
112 | int design_voltage; | 115 | int design_voltage; |
113 | int design_capacity_warning; | 116 | int design_capacity_warning; |
114 | int design_capacity_low; | 117 | int design_capacity_low; |
118 | int cycle_count; | ||
119 | int measurement_accuracy; | ||
120 | int max_sampling_time; | ||
121 | int min_sampling_time; | ||
122 | int max_averaging_interval; | ||
123 | int min_averaging_interval; | ||
115 | int capacity_granularity_1; | 124 | int capacity_granularity_1; |
116 | int capacity_granularity_2; | 125 | int capacity_granularity_2; |
117 | int alarm; | 126 | int alarm; |
@@ -200,6 +209,9 @@ static int acpi_battery_get_property(struct power_supply *psy, | |||
200 | case POWER_SUPPLY_PROP_TECHNOLOGY: | 209 | case POWER_SUPPLY_PROP_TECHNOLOGY: |
201 | val->intval = acpi_battery_technology(battery); | 210 | val->intval = acpi_battery_technology(battery); |
202 | break; | 211 | break; |
212 | case POWER_SUPPLY_PROP_CYCLE_COUNT: | ||
213 | val->intval = battery->cycle_count; | ||
214 | break; | ||
203 | case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: | 215 | case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: |
204 | val->intval = battery->design_voltage * 1000; | 216 | val->intval = battery->design_voltage * 1000; |
205 | break; | 217 | break; |
@@ -241,6 +253,7 @@ static enum power_supply_property charge_battery_props[] = { | |||
241 | POWER_SUPPLY_PROP_STATUS, | 253 | POWER_SUPPLY_PROP_STATUS, |
242 | POWER_SUPPLY_PROP_PRESENT, | 254 | POWER_SUPPLY_PROP_PRESENT, |
243 | POWER_SUPPLY_PROP_TECHNOLOGY, | 255 | POWER_SUPPLY_PROP_TECHNOLOGY, |
256 | POWER_SUPPLY_PROP_CYCLE_COUNT, | ||
244 | POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, | 257 | POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, |
245 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | 258 | POWER_SUPPLY_PROP_VOLTAGE_NOW, |
246 | POWER_SUPPLY_PROP_CURRENT_NOW, | 259 | POWER_SUPPLY_PROP_CURRENT_NOW, |
@@ -256,6 +269,7 @@ static enum power_supply_property energy_battery_props[] = { | |||
256 | POWER_SUPPLY_PROP_STATUS, | 269 | POWER_SUPPLY_PROP_STATUS, |
257 | POWER_SUPPLY_PROP_PRESENT, | 270 | POWER_SUPPLY_PROP_PRESENT, |
258 | POWER_SUPPLY_PROP_TECHNOLOGY, | 271 | POWER_SUPPLY_PROP_TECHNOLOGY, |
272 | POWER_SUPPLY_PROP_CYCLE_COUNT, | ||
259 | POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, | 273 | POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, |
260 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | 274 | POWER_SUPPLY_PROP_VOLTAGE_NOW, |
261 | POWER_SUPPLY_PROP_CURRENT_NOW, | 275 | POWER_SUPPLY_PROP_CURRENT_NOW, |
@@ -307,6 +321,28 @@ static struct acpi_offsets info_offsets[] = { | |||
307 | {offsetof(struct acpi_battery, oem_info), 1}, | 321 | {offsetof(struct acpi_battery, oem_info), 1}, |
308 | }; | 322 | }; |
309 | 323 | ||
324 | static struct acpi_offsets extended_info_offsets[] = { | ||
325 | {offsetof(struct acpi_battery, power_unit), 0}, | ||
326 | {offsetof(struct acpi_battery, design_capacity), 0}, | ||
327 | {offsetof(struct acpi_battery, full_charge_capacity), 0}, | ||
328 | {offsetof(struct acpi_battery, technology), 0}, | ||
329 | {offsetof(struct acpi_battery, design_voltage), 0}, | ||
330 | {offsetof(struct acpi_battery, design_capacity_warning), 0}, | ||
331 | {offsetof(struct acpi_battery, design_capacity_low), 0}, | ||
332 | {offsetof(struct acpi_battery, cycle_count), 0}, | ||
333 | {offsetof(struct acpi_battery, measurement_accuracy), 0}, | ||
334 | {offsetof(struct acpi_battery, max_sampling_time), 0}, | ||
335 | {offsetof(struct acpi_battery, min_sampling_time), 0}, | ||
336 | {offsetof(struct acpi_battery, max_averaging_interval), 0}, | ||
337 | {offsetof(struct acpi_battery, min_averaging_interval), 0}, | ||
338 | {offsetof(struct acpi_battery, capacity_granularity_1), 0}, | ||
339 | {offsetof(struct acpi_battery, capacity_granularity_2), 0}, | ||
340 | {offsetof(struct acpi_battery, model_number), 1}, | ||
341 | {offsetof(struct acpi_battery, serial_number), 1}, | ||
342 | {offsetof(struct acpi_battery, type), 1}, | ||
343 | {offsetof(struct acpi_battery, oem_info), 1}, | ||
344 | }; | ||
345 | |||
310 | static int extract_package(struct acpi_battery *battery, | 346 | static int extract_package(struct acpi_battery *battery, |
311 | union acpi_object *package, | 347 | union acpi_object *package, |
312 | struct acpi_offsets *offsets, int num) | 348 | struct acpi_offsets *offsets, int num) |
@@ -352,22 +388,29 @@ static int acpi_battery_get_info(struct acpi_battery *battery) | |||
352 | { | 388 | { |
353 | int result = -EFAULT; | 389 | int result = -EFAULT; |
354 | acpi_status status = 0; | 390 | acpi_status status = 0; |
391 | char *name = test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags)? | ||
392 | "_BIX" : "_BIF"; | ||
393 | |||
355 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | 394 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; |
356 | 395 | ||
357 | if (!acpi_battery_present(battery)) | 396 | if (!acpi_battery_present(battery)) |
358 | return 0; | 397 | return 0; |
359 | mutex_lock(&battery->lock); | 398 | mutex_lock(&battery->lock); |
360 | status = acpi_evaluate_object(battery->device->handle, "_BIF", | 399 | status = acpi_evaluate_object(battery->device->handle, name, |
361 | NULL, &buffer); | 400 | NULL, &buffer); |
362 | mutex_unlock(&battery->lock); | 401 | mutex_unlock(&battery->lock); |
363 | 402 | ||
364 | if (ACPI_FAILURE(status)) { | 403 | if (ACPI_FAILURE(status)) { |
365 | ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BIF")); | 404 | ACPI_EXCEPTION((AE_INFO, status, "Evaluating %s", name)); |
366 | return -ENODEV; | 405 | return -ENODEV; |
367 | } | 406 | } |
368 | 407 | if (test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags)) | |
369 | result = extract_package(battery, buffer.pointer, | 408 | result = extract_package(battery, buffer.pointer, |
370 | info_offsets, ARRAY_SIZE(info_offsets)); | 409 | extended_info_offsets, |
410 | ARRAY_SIZE(extended_info_offsets)); | ||
411 | else | ||
412 | result = extract_package(battery, buffer.pointer, | ||
413 | info_offsets, ARRAY_SIZE(info_offsets)); | ||
371 | kfree(buffer.pointer); | 414 | kfree(buffer.pointer); |
372 | return result; | 415 | return result; |
373 | } | 416 | } |
@@ -414,7 +457,7 @@ static int acpi_battery_set_alarm(struct acpi_battery *battery) | |||
414 | union acpi_object arg0 = { .type = ACPI_TYPE_INTEGER }; | 457 | union acpi_object arg0 = { .type = ACPI_TYPE_INTEGER }; |
415 | struct acpi_object_list arg_list = { 1, &arg0 }; | 458 | struct acpi_object_list arg_list = { 1, &arg0 }; |
416 | 459 | ||
417 | if (!acpi_battery_present(battery)|| | 460 | if (!acpi_battery_present(battery) || |
418 | !test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags)) | 461 | !test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags)) |
419 | return -ENODEV; | 462 | return -ENODEV; |
420 | 463 | ||
@@ -592,6 +635,7 @@ static int acpi_battery_print_info(struct seq_file *seq, int result) | |||
592 | seq_printf(seq, "design capacity low: %d %sh\n", | 635 | seq_printf(seq, "design capacity low: %d %sh\n", |
593 | battery->design_capacity_low, | 636 | battery->design_capacity_low, |
594 | acpi_battery_units(battery)); | 637 | acpi_battery_units(battery)); |
638 | seq_printf(seq, "cycle count: %i\n", battery->cycle_count); | ||
595 | seq_printf(seq, "capacity granularity 1: %d %sh\n", | 639 | seq_printf(seq, "capacity granularity 1: %d %sh\n", |
596 | battery->capacity_granularity_1, | 640 | battery->capacity_granularity_1, |
597 | acpi_battery_units(battery)); | 641 | acpi_battery_units(battery)); |
@@ -843,6 +887,7 @@ static int acpi_battery_add(struct acpi_device *device) | |||
843 | { | 887 | { |
844 | int result = 0; | 888 | int result = 0; |
845 | struct acpi_battery *battery = NULL; | 889 | struct acpi_battery *battery = NULL; |
890 | acpi_handle handle; | ||
846 | if (!device) | 891 | if (!device) |
847 | return -EINVAL; | 892 | return -EINVAL; |
848 | battery = kzalloc(sizeof(struct acpi_battery), GFP_KERNEL); | 893 | battery = kzalloc(sizeof(struct acpi_battery), GFP_KERNEL); |
@@ -853,6 +898,9 @@ static int acpi_battery_add(struct acpi_device *device) | |||
853 | strcpy(acpi_device_class(device), ACPI_BATTERY_CLASS); | 898 | strcpy(acpi_device_class(device), ACPI_BATTERY_CLASS); |
854 | device->driver_data = battery; | 899 | device->driver_data = battery; |
855 | mutex_init(&battery->lock); | 900 | mutex_init(&battery->lock); |
901 | if (ACPI_SUCCESS(acpi_get_handle(battery->device->handle, | ||
902 | "_BIX", &handle))) | ||
903 | set_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags); | ||
856 | acpi_battery_update(battery); | 904 | acpi_battery_update(battery); |
857 | #ifdef CONFIG_ACPI_PROCFS_POWER | 905 | #ifdef CONFIG_ACPI_PROCFS_POWER |
858 | result = acpi_battery_add_fs(device); | 906 | result = acpi_battery_add_fs(device); |