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

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: Song Hongyan <hongyan.song@intel.com>
Acked-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
Cc: <Stable@vger.kernel.org>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>
This commit is contained in:
Song Hongyan 2016-10-25 01:30:07 +00:00 committed by Jonathan Cameron
parent 8af644a7d6
commit 6f77199e9e

View File

@ -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 {
{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);
/* /*
* 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,
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,
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);