| From 480d3771eb4a34ad8f4240aa80d2a6b1711fa53c Mon Sep 17 00:00:00 2001 |
| From: Bjorn Andersson <bjorn.andersson@linaro.org> |
| Date: Sun, 23 Dec 2018 23:26:44 -0800 |
| Subject: thermal: generic-adc: Fix adc to temp interpolation |
| |
| [ Upstream commit 9d216211fded20fff301d0317af3238d8383634c ] |
| |
| First correct the edge case to return the last element if we're |
| outside the range, rather than at the last element, so that |
| interpolation is not omitted for points between the two last entries in |
| the table. |
| |
| Then correct the formula to perform linear interpolation based the two |
| points surrounding the read ADC value. The indices for temp are kept as |
| "hi" and "lo" to pair with the adc indices, but there's no requirement |
| that the temperature is provided in descendent order. mult_frac() is |
| used to prevent issues with overflowing the int. |
| |
| Cc: Laxman Dewangan <ldewangan@nvidia.com> |
| Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org> |
| Signed-off-by: Eduardo Valentin <edubezval@gmail.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/thermal/thermal-generic-adc.c | 12 ++++++++---- |
| 1 file changed, 8 insertions(+), 4 deletions(-) |
| |
| diff --git a/drivers/thermal/thermal-generic-adc.c b/drivers/thermal/thermal-generic-adc.c |
| index 73f55d6a1721..ad601e5b4175 100644 |
| --- a/drivers/thermal/thermal-generic-adc.c |
| +++ b/drivers/thermal/thermal-generic-adc.c |
| @@ -26,7 +26,7 @@ struct gadc_thermal_info { |
| |
| static int gadc_thermal_adc_to_temp(struct gadc_thermal_info *gti, int val) |
| { |
| - int temp, adc_hi, adc_lo; |
| + int temp, temp_hi, temp_lo, adc_hi, adc_lo; |
| int i; |
| |
| for (i = 0; i < gti->nlookup_table; i++) { |
| @@ -36,13 +36,17 @@ static int gadc_thermal_adc_to_temp(struct gadc_thermal_info *gti, int val) |
| |
| if (i == 0) { |
| temp = gti->lookup_table[0]; |
| - } else if (i >= (gti->nlookup_table - 1)) { |
| + } else if (i >= gti->nlookup_table) { |
| temp = gti->lookup_table[2 * (gti->nlookup_table - 1)]; |
| } else { |
| adc_hi = gti->lookup_table[2 * i - 1]; |
| adc_lo = gti->lookup_table[2 * i + 1]; |
| - temp = gti->lookup_table[2 * i]; |
| - temp -= ((val - adc_lo) * 1000) / (adc_hi - adc_lo); |
| + |
| + temp_hi = gti->lookup_table[2 * i - 2]; |
| + temp_lo = gti->lookup_table[2 * i]; |
| + |
| + temp = temp_hi + mult_frac(temp_lo - temp_hi, val - adc_hi, |
| + adc_lo - adc_hi); |
| } |
| |
| return temp; |
| -- |
| 2.19.1 |
| |