Commit 34a019a4 authored by Song Hongyan's avatar Song Hongyan Committed by Luis Henriques

iio: hid-sensors: Increase the precision of scale to fix wrong reading interpretation.

BugLink: http://bugs.launchpad.net/bugs/1642968

commit 6f77199e upstream.

While testing, it was observed that on some platforms the scale value
from iio sysfs for gyroscope is always 0 (E.g. Yoga 260). This results
in the final angular velocity component values to be zeros.

This is caused by insufficient precision of scale value displayed in sysfs.
If the precision is changed to nano from current micro, then this is
sufficient to display the scale value on this platform.
Since this can be a problem for all other HID sensors, increase scale
precision of all HID sensors to nano from current micro.

Results on Yoga 260:

name		scale before	scale now
--------------------------------------------
gyro_3d		0.000000	0.000000174
als			0.001000	0.001000000
magn_3d		0.000001	0.000001000
accel_3d		0.000009	0.000009806
Signed-off-by: default avatarSong Hongyan <hongyan.song@intel.com>
Acked-by: default avatarSrinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
Signed-off-by: default avatarJonathan Cameron <jic23@kernel.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarTim Gardner <tim.gardner@canonical.com>
parent c1c51edb
...@@ -30,26 +30,26 @@ static struct { ...@@ -30,26 +30,26 @@ static struct {
u32 usage_id; u32 usage_id;
int unit; /* 0 for default others from HID sensor spec */ int unit; /* 0 for default others from HID sensor spec */
int scale_val0; /* scale, whole number */ int scale_val0; /* scale, whole number */
int scale_val1; /* scale, fraction in micros */ int scale_val1; /* scale, fraction in nanos */
} unit_conversion[] = { } unit_conversion[] = {
{HID_USAGE_SENSOR_ACCEL_3D, 0, 9, 806650}, {HID_USAGE_SENSOR_ACCEL_3D, 0, 9, 806650000},
{HID_USAGE_SENSOR_ACCEL_3D, {HID_USAGE_SENSOR_ACCEL_3D,
HID_USAGE_SENSOR_UNITS_METERS_PER_SEC_SQRD, 1, 0}, HID_USAGE_SENSOR_UNITS_METERS_PER_SEC_SQRD, 1, 0},
{HID_USAGE_SENSOR_ACCEL_3D, {HID_USAGE_SENSOR_ACCEL_3D,
HID_USAGE_SENSOR_UNITS_G, 9, 806650}, HID_USAGE_SENSOR_UNITS_G, 9, 806650000},
{HID_USAGE_SENSOR_GYRO_3D, 0, 0, 17453}, {HID_USAGE_SENSOR_GYRO_3D, 0, 0, 17453293},
{HID_USAGE_SENSOR_GYRO_3D, {HID_USAGE_SENSOR_GYRO_3D,
HID_USAGE_SENSOR_UNITS_RADIANS_PER_SECOND, 1, 0}, HID_USAGE_SENSOR_UNITS_RADIANS_PER_SECOND, 1, 0},
{HID_USAGE_SENSOR_GYRO_3D, {HID_USAGE_SENSOR_GYRO_3D,
HID_USAGE_SENSOR_UNITS_DEGREES_PER_SECOND, 0, 17453}, HID_USAGE_SENSOR_UNITS_DEGREES_PER_SECOND, 0, 17453293},
{HID_USAGE_SENSOR_COMPASS_3D, 0, 0, 1000}, {HID_USAGE_SENSOR_COMPASS_3D, 0, 0, 1000000},
{HID_USAGE_SENSOR_COMPASS_3D, HID_USAGE_SENSOR_UNITS_GAUSS, 1, 0}, {HID_USAGE_SENSOR_COMPASS_3D, HID_USAGE_SENSOR_UNITS_GAUSS, 1, 0},
{HID_USAGE_SENSOR_INCLINOMETER_3D, 0, 0, 17453}, {HID_USAGE_SENSOR_INCLINOMETER_3D, 0, 0, 17453293},
{HID_USAGE_SENSOR_INCLINOMETER_3D, {HID_USAGE_SENSOR_INCLINOMETER_3D,
HID_USAGE_SENSOR_UNITS_DEGREES, 0, 17453}, HID_USAGE_SENSOR_UNITS_DEGREES, 0, 17453293},
{HID_USAGE_SENSOR_INCLINOMETER_3D, {HID_USAGE_SENSOR_INCLINOMETER_3D,
HID_USAGE_SENSOR_UNITS_RADIANS, 1, 0}, HID_USAGE_SENSOR_UNITS_RADIANS, 1, 0},
...@@ -57,7 +57,7 @@ static struct { ...@@ -57,7 +57,7 @@ static struct {
{HID_USAGE_SENSOR_ALS, HID_USAGE_SENSOR_UNITS_LUX, 1, 0}, {HID_USAGE_SENSOR_ALS, HID_USAGE_SENSOR_UNITS_LUX, 1, 0},
{HID_USAGE_SENSOR_PRESSURE, 0, 100, 0}, {HID_USAGE_SENSOR_PRESSURE, 0, 100, 0},
{HID_USAGE_SENSOR_PRESSURE, HID_USAGE_SENSOR_UNITS_PASCAL, 0, 1000}, {HID_USAGE_SENSOR_PRESSURE, HID_USAGE_SENSOR_UNITS_PASCAL, 0, 1000000},
}; };
static int pow_10(unsigned power) static int pow_10(unsigned power)
...@@ -266,15 +266,15 @@ EXPORT_SYMBOL(hid_sensor_write_raw_hyst_value); ...@@ -266,15 +266,15 @@ EXPORT_SYMBOL(hid_sensor_write_raw_hyst_value);
/* /*
* This fuction applies the unit exponent to the scale. * This fuction applies the unit exponent to the scale.
* For example: * For example:
* 9.806650 ->exp:2-> val0[980]val1[665000] * 9.806650000 ->exp:2-> val0[980]val1[665000000]
* 9.000806 ->exp:2-> val0[900]val1[80600] * 9.000806000 ->exp:2-> val0[900]val1[80600000]
* 0.174535 ->exp:2-> val0[17]val1[453500] * 0.174535293 ->exp:2-> val0[17]val1[453529300]
* 1.001745 ->exp:0-> val0[1]val1[1745] * 1.001745329 ->exp:0-> val0[1]val1[1745329]
* 1.001745 ->exp:2-> val0[100]val1[174500] * 1.001745329 ->exp:2-> val0[100]val1[174532900]
* 1.001745 ->exp:4-> val0[10017]val1[450000] * 1.001745329 ->exp:4-> val0[10017]val1[453290000]
* 9.806650 ->exp:-2-> val0[0]val1[98066] * 9.806650000 ->exp:-2-> val0[0]val1[98066500]
*/ */
static void adjust_exponent_micro(int *val0, int *val1, int scale0, static void adjust_exponent_nano(int *val0, int *val1, int scale0,
int scale1, int exp) int scale1, int exp)
{ {
int i; int i;
...@@ -285,32 +285,32 @@ static void adjust_exponent_micro(int *val0, int *val1, int scale0, ...@@ -285,32 +285,32 @@ static void adjust_exponent_micro(int *val0, int *val1, int scale0,
if (exp > 0) { if (exp > 0) {
*val0 = scale0 * pow_10(exp); *val0 = scale0 * pow_10(exp);
res = 0; res = 0;
if (exp > 6) { if (exp > 9) {
*val1 = 0; *val1 = 0;
return; return;
} }
for (i = 0; i < exp; ++i) { for (i = 0; i < exp; ++i) {
x = scale1 / pow_10(5 - i); x = scale1 / pow_10(8 - i);
res += (pow_10(exp - 1 - i) * x); res += (pow_10(exp - 1 - i) * x);
scale1 = scale1 % pow_10(5 - i); scale1 = scale1 % pow_10(8 - i);
} }
*val0 += res; *val0 += res;
*val1 = scale1 * pow_10(exp); *val1 = scale1 * pow_10(exp);
} else if (exp < 0) { } else if (exp < 0) {
exp = abs(exp); exp = abs(exp);
if (exp > 6) { if (exp > 9) {
*val0 = *val1 = 0; *val0 = *val1 = 0;
return; return;
} }
*val0 = scale0 / pow_10(exp); *val0 = scale0 / pow_10(exp);
rem = scale0 % pow_10(exp); rem = scale0 % pow_10(exp);
res = 0; res = 0;
for (i = 0; i < (6 - exp); ++i) { for (i = 0; i < (9 - exp); ++i) {
x = scale1 / pow_10(5 - i); x = scale1 / pow_10(8 - i);
res += (pow_10(5 - exp - i) * x); res += (pow_10(8 - exp - i) * x);
scale1 = scale1 % pow_10(5 - i); scale1 = scale1 % pow_10(8 - i);
} }
*val1 = rem * pow_10(6 - exp) + res; *val1 = rem * pow_10(9 - exp) + res;
} else { } else {
*val0 = scale0; *val0 = scale0;
*val1 = scale1; *val1 = scale1;
...@@ -332,14 +332,14 @@ int hid_sensor_format_scale(u32 usage_id, ...@@ -332,14 +332,14 @@ int hid_sensor_format_scale(u32 usage_id,
unit_conversion[i].unit == attr_info->units) { unit_conversion[i].unit == attr_info->units) {
exp = hid_sensor_convert_exponent( exp = hid_sensor_convert_exponent(
attr_info->unit_expo); attr_info->unit_expo);
adjust_exponent_micro(val0, val1, adjust_exponent_nano(val0, val1,
unit_conversion[i].scale_val0, unit_conversion[i].scale_val0,
unit_conversion[i].scale_val1, exp); unit_conversion[i].scale_val1, exp);
break; break;
} }
} }
return IIO_VAL_INT_PLUS_MICRO; return IIO_VAL_INT_PLUS_NANO;
} }
EXPORT_SYMBOL(hid_sensor_format_scale); EXPORT_SYMBOL(hid_sensor_format_scale);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment