aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
authorJean Delvare <khali@linux-fr.org>2009-04-06 10:01:46 -0400
committerLen Brown <len.brown@intel.com>2009-04-07 01:37:27 -0400
commit13614e37e94da4606a300ee6fe25c8c4a19ee670 (patch)
tree648a67c5436fde7470b59965198e96bb6e2c399f /drivers/acpi
parentd508afb437daee7cf07da085b635c44a4ebf9b38 (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.c41
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
586static int thermal_get_temp(struct thermal_zone_device *thermal, 587static 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 */
1353static 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
1337static int acpi_thermal_add(struct acpi_device *device) 1362static 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;