diff options
author | Jean Delvare <khali@linux-fr.org> | 2009-04-06 10:01:46 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2009-04-07 01:37:27 -0400 |
commit | 13614e37e94da4606a300ee6fe25c8c4a19ee670 (patch) | |
tree | 648a67c5436fde7470b59965198e96bb6e2c399f /drivers/acpi | |
parent | d508afb437daee7cf07da085b635c44a4ebf9b38 (diff) |
ACPI: Adjust Kelvin offset to match local implementation
The exact offset between Kelvin and degree Celsius is 273.15. However
ACPI handles temperature values with a single decimal place. As a
consequence, some implementations use an offset of 273.1 and others
use an offset of 273.2. Try to find out which one is being used, to
present the most accurate and visually appealing number.
Tested on a Sony Vaio PGC-GR214EP (which uses 273.1) and a Lenovo
Thinkpad T60p (which uses 273.2).
Signed-off-by: Jean Delvare <khali@linux-fr.org>
Acked-by: Zhang Rui <rui.zhang@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/thermal.c | 41 |
1 files changed, 34 insertions, 7 deletions
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index e8c143caf0fd..ddbb7c8f994d 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c | |||
@@ -192,6 +192,7 @@ struct acpi_thermal { | |||
192 | struct acpi_handle_list devices; | 192 | struct acpi_handle_list devices; |
193 | struct thermal_zone_device *thermal_zone; | 193 | struct thermal_zone_device *thermal_zone; |
194 | int tz_enabled; | 194 | int tz_enabled; |
195 | int kelvin_offset; | ||
195 | struct mutex lock; | 196 | struct mutex lock; |
196 | }; | 197 | }; |
197 | 198 | ||
@@ -581,7 +582,7 @@ static void acpi_thermal_check(void *data) | |||
581 | } | 582 | } |
582 | 583 | ||
583 | /* sys I/F for generic thermal sysfs support */ | 584 | /* sys I/F for generic thermal sysfs support */ |
584 | #define KELVIN_TO_MILLICELSIUS(t) (t * 100 - 273200) | 585 | #define KELVIN_TO_MILLICELSIUS(t, off) (((t) - (off)) * 100) |
585 | 586 | ||
586 | static int thermal_get_temp(struct thermal_zone_device *thermal, | 587 | static int thermal_get_temp(struct thermal_zone_device *thermal, |
587 | unsigned long *temp) | 588 | unsigned long *temp) |
@@ -596,7 +597,7 @@ static int thermal_get_temp(struct thermal_zone_device *thermal, | |||
596 | if (result) | 597 | if (result) |
597 | return result; | 598 | return result; |
598 | 599 | ||
599 | *temp = KELVIN_TO_MILLICELSIUS(tz->temperature); | 600 | *temp = KELVIN_TO_MILLICELSIUS(tz->temperature, tz->kelvin_offset); |
600 | return 0; | 601 | return 0; |
601 | } | 602 | } |
602 | 603 | ||
@@ -702,7 +703,8 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal, | |||
702 | if (tz->trips.critical.flags.valid) { | 703 | if (tz->trips.critical.flags.valid) { |
703 | if (!trip) { | 704 | if (!trip) { |
704 | *temp = KELVIN_TO_MILLICELSIUS( | 705 | *temp = KELVIN_TO_MILLICELSIUS( |
705 | tz->trips.critical.temperature); | 706 | tz->trips.critical.temperature, |
707 | tz->kelvin_offset); | ||
706 | return 0; | 708 | return 0; |
707 | } | 709 | } |
708 | trip--; | 710 | trip--; |
@@ -711,7 +713,8 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal, | |||
711 | if (tz->trips.hot.flags.valid) { | 713 | if (tz->trips.hot.flags.valid) { |
712 | if (!trip) { | 714 | if (!trip) { |
713 | *temp = KELVIN_TO_MILLICELSIUS( | 715 | *temp = KELVIN_TO_MILLICELSIUS( |
714 | tz->trips.hot.temperature); | 716 | tz->trips.hot.temperature, |
717 | tz->kelvin_offset); | ||
715 | return 0; | 718 | return 0; |
716 | } | 719 | } |
717 | trip--; | 720 | trip--; |
@@ -720,7 +723,8 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal, | |||
720 | if (tz->trips.passive.flags.valid) { | 723 | if (tz->trips.passive.flags.valid) { |
721 | if (!trip) { | 724 | if (!trip) { |
722 | *temp = KELVIN_TO_MILLICELSIUS( | 725 | *temp = KELVIN_TO_MILLICELSIUS( |
723 | tz->trips.passive.temperature); | 726 | tz->trips.passive.temperature, |
727 | tz->kelvin_offset); | ||
724 | return 0; | 728 | return 0; |
725 | } | 729 | } |
726 | trip--; | 730 | trip--; |
@@ -730,7 +734,8 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal, | |||
730 | tz->trips.active[i].flags.valid; i++) { | 734 | tz->trips.active[i].flags.valid; i++) { |
731 | if (!trip) { | 735 | if (!trip) { |
732 | *temp = KELVIN_TO_MILLICELSIUS( | 736 | *temp = KELVIN_TO_MILLICELSIUS( |
733 | tz->trips.active[i].temperature); | 737 | tz->trips.active[i].temperature, |
738 | tz->kelvin_offset); | ||
734 | return 0; | 739 | return 0; |
735 | } | 740 | } |
736 | trip--; | 741 | trip--; |
@@ -745,7 +750,8 @@ static int thermal_get_crit_temp(struct thermal_zone_device *thermal, | |||
745 | 750 | ||
746 | if (tz->trips.critical.flags.valid) { | 751 | if (tz->trips.critical.flags.valid) { |
747 | *temperature = KELVIN_TO_MILLICELSIUS( | 752 | *temperature = KELVIN_TO_MILLICELSIUS( |
748 | tz->trips.critical.temperature); | 753 | tz->trips.critical.temperature, |
754 | tz->kelvin_offset); | ||
749 | return 0; | 755 | return 0; |
750 | } else | 756 | } else |
751 | return -EINVAL; | 757 | return -EINVAL; |
@@ -1334,6 +1340,25 @@ static int acpi_thermal_get_info(struct acpi_thermal *tz) | |||
1334 | return 0; | 1340 | return 0; |
1335 | } | 1341 | } |
1336 | 1342 | ||
1343 | /* | ||
1344 | * The exact offset between Kelvin and degree Celsius is 273.15. However ACPI | ||
1345 | * handles temperature values with a single decimal place. As a consequence, | ||
1346 | * some implementations use an offset of 273.1 and others use an offset of | ||
1347 | * 273.2. Try to find out which one is being used, to present the most | ||
1348 | * accurate and visually appealing number. | ||
1349 | * | ||
1350 | * The heuristic below should work for all ACPI thermal zones which have a | ||
1351 | * critical trip point with a value being a multiple of 0.5 degree Celsius. | ||
1352 | */ | ||
1353 | static void acpi_thermal_guess_offset(struct acpi_thermal *tz) | ||
1354 | { | ||
1355 | if (tz->trips.critical.flags.valid && | ||
1356 | (tz->trips.critical.temperature % 5) == 1) | ||
1357 | tz->kelvin_offset = 2731; | ||
1358 | else | ||
1359 | tz->kelvin_offset = 2732; | ||
1360 | } | ||
1361 | |||
1337 | static int acpi_thermal_add(struct acpi_device *device) | 1362 | static int acpi_thermal_add(struct acpi_device *device) |
1338 | { | 1363 | { |
1339 | int result = 0; | 1364 | int result = 0; |
@@ -1360,6 +1385,8 @@ static int acpi_thermal_add(struct acpi_device *device) | |||
1360 | if (result) | 1385 | if (result) |
1361 | goto free_memory; | 1386 | goto free_memory; |
1362 | 1387 | ||
1388 | acpi_thermal_guess_offset(tz); | ||
1389 | |||
1363 | result = acpi_thermal_register_thermal_zone(tz); | 1390 | result = acpi_thermal_register_thermal_zone(tz); |
1364 | if (result) | 1391 | if (result) |
1365 | goto free_memory; | 1392 | goto free_memory; |