From 1e9a1aea7a05a1c8a7ece72b02d8077089f9e4d5 Mon Sep 17 00:00:00 2001 From: Caesar Wang Date: Sun, 25 Jan 2015 10:11:11 +0800 Subject: thermal: rockchip: make temperature reporting much more accurate In general, the kernel should report temperature readings exactly as reported by the hardware. The cpu / gpu thermal driver works in 5 degree increments,but we ought to do more accurate. The temperature will do linear interpolation between the entries in the table. Test= $md5sum /dev/zero & $while true; do grep "" /sys/class/thermal/thermal_zone[1-2]/temp; sleep .5; done e.g. We can get the result as follows: /sys/class/thermal/thermal_zone1/temp:39994 /sys/class/thermal/thermal_zone2/temp:39086 /sys/class/thermal/thermal_zone1/temp:39994 /sys/class/thermal/thermal_zone2/temp:39540 /sys/class/thermal/thermal_zone1/temp:39540 /sys/class/thermal/thermal_zone2/temp:39540 /sys/class/thermal/thermal_zone1/temp:39540 /sys/class/thermal/thermal_zone2/temp:39994 Reviewed-by: Dmitry Torokhov Reviewed-by: Daniel Kurtz Signed-off-by: Caesar Wang Signed-off-by: Eduardo Valentin --- drivers/thermal/rockchip_thermal.c | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/rockchip_thermal.c b/drivers/thermal/rockchip_thermal.c index 9c6ce548e363..3aa46ac7cdbc 100644 --- a/drivers/thermal/rockchip_thermal.c +++ b/drivers/thermal/rockchip_thermal.c @@ -193,19 +193,20 @@ static u32 rk_tsadcv2_temp_to_code(long temp) static long rk_tsadcv2_code_to_temp(u32 code) { - int high, low, mid; - - low = 0; - high = ARRAY_SIZE(v2_code_table) - 1; - mid = (high + low) / 2; - - if (code > v2_code_table[low].code || code < v2_code_table[high].code) - return 125000; /* No code available, return max temperature */ + unsigned int low = 0; + unsigned int high = ARRAY_SIZE(v2_code_table) - 1; + unsigned int mid = (low + high) / 2; + unsigned int num; + unsigned long denom; + + /* Invalid code, return -EAGAIN */ + if (code > TSADCV2_DATA_MASK) + return -EAGAIN; - while (low <= high) { - if (code >= v2_code_table[mid].code && code < - v2_code_table[mid - 1].code) - return v2_code_table[mid].temp; + while (low <= high && mid) { + if (code >= v2_code_table[mid].code && + code < v2_code_table[mid - 1].code) + break; else if (code < v2_code_table[mid].code) low = mid + 1; else @@ -213,7 +214,16 @@ static long rk_tsadcv2_code_to_temp(u32 code) mid = (low + high) / 2; } - return 125000; + /* + * The 5C granularity provided by the table is too much. Let's + * assume that the relationship between sensor readings and + * temperature between 2 table entries is linear and interpolate + * to produce less granular result. + */ + num = v2_code_table[mid].temp - v2_code_table[mid - 1].temp; + num *= v2_code_table[mid - 1].code - code; + denom = v2_code_table[mid - 1].code - v2_code_table[mid].code; + return v2_code_table[mid - 1].temp + (num / denom); } /** -- cgit v1.2.3