Second set of IIO fixes for the 4.9 cycle.

Interestingly scale related fixes for accelerometers at both ends of
 the range.  Obviously more varied devices turning up than we've seen before!
 
 * ad5933
   - fix an uninitialized value in a return case that is winding up GCC.
 * hid sensors
   - missing pm function prevents hid rotations sensors from working on newer
   ISH hubs (works by luck on older ones)
   - increase of scale precision needed to fix a case where on a yoga 260
   the reported scale is 0 (presumably a high precision but very low g sensor).
 * st_sensors
   - fix an issue seen with the hs3lis331dl where the range is much greater
   than previous devices (100's of g) and hence the per bit scale is greater
   than 1.
 -----BEGIN PGP SIGNATURE-----
 
 iQIuBAABCAAYBQJYH3AgERxqaWMyM0BrZXJuZWwub3JnAAoJEFSFNJnE9BaI7s0P
 /RitgKHURPOdUS51Y19slkC/K6S4QaSD7DzH8jRtEmR9iZJjJJwE0ZgCQcmcwd70
 tlKZU0PoQcfU6zL0tmW8HX7A48IWfSETLa5Uxv+7lY11u2VLXpMLvMjlJWXYrKPK
 FXUUpLacPhER91VlAQpmQKeGuuo8DhGp4tUUeSTCH+RDfKSluN8cOUFAfFMrN6FT
 GDuXxKGrLcyKjXW/OvNsimsJyyx8BGrLMCwjJbikTmvHCh2AztCFkgt3rTemU9Xh
 fwamxWZu3ezP6+gj554+PNQOe4Z+h3869hzEWu3Oa93ez5cFINm/f258GjfNQP1q
 JA57kCwx3nb4SNYHvG7TK154aYQzq5YTkuSEeCz7SUP7WNSWwzBISHJ0ZH++ymIK
 smIqXTMg8SKgxBupba5JOyc6lI/5t6sKiB0iROxrWbTDEh4jGFdCwcNL2duarWMx
 As4Tgu/3TnhuWA+7MY0FZB4Es0JBdaeXK5D6OKiy0T/6N/m0fzYhX72Fk47LHX4m
 WV855PifjjCBqnll4JT49ijXF81E4JZkwl2s2t7K0u43OEjv36L9PfpcKL0xKGx3
 XepjqJiC4MPlJj2sKSmOEtq2G+AcGphW/1vbKhLjRva4OphiV78lMKIiSTWi9IaN
 LIFVCGe149i1xCH5LQQKDvX+wGMgUsXLl/aCezKd2dLE
 =KcFP
 -----END PGP SIGNATURE-----

Merge tag 'iio-fixes-for-4.9b' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into staging-linus

Second set of IIO fixes for the 4.9 cycle.

Interestingly scale related fixes for accelerometers at both ends of
the range.  Obviously more varied devices turning up than we've seen before!

* ad5933
  - fix an uninitialized value in a return case that is winding up GCC.
* hid sensors
  - missing pm function prevents hid rotations sensors from working on newer
  ISH hubs (works by luck on older ones)
  - increase of scale precision needed to fix a case where on a yoga 260
  the reported scale is 0 (presumably a high precision but very low g sensor).
* st_sensors
  - fix an issue seen with the hs3lis331dl where the range is much greater
  than previous devices (100's of g) and hence the per bit scale is greater
  than 1.
This commit is contained in:
Greg Kroah-Hartman 2016-11-07 09:42:27 +01:00
commit 371c6d9727
5 changed files with 52 additions and 42 deletions

View file

@ -743,8 +743,8 @@ static int st_accel_read_raw(struct iio_dev *indio_dev,
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
*val = 0;
*val2 = adata->current_fullscale->gain;
*val = adata->current_fullscale->gain / 1000000;
*val2 = adata->current_fullscale->gain % 1000000;
return IIO_VAL_INT_PLUS_MICRO;
case IIO_CHAN_INFO_SAMP_FREQ:
*val = adata->odr;
@ -763,9 +763,13 @@ static int st_accel_write_raw(struct iio_dev *indio_dev,
int err;
switch (mask) {
case IIO_CHAN_INFO_SCALE:
err = st_sensors_set_fullscale_by_gain(indio_dev, val2);
case IIO_CHAN_INFO_SCALE: {
int gain;
gain = val * 1000000 + val2;
err = st_sensors_set_fullscale_by_gain(indio_dev, gain);
break;
}
case IIO_CHAN_INFO_SAMP_FREQ:
if (val2)
return -EINVAL;

View file

@ -30,26 +30,26 @@ static struct {
u32 usage_id;
int unit; /* 0 for default others from HID sensor spec */
int scale_val0; /* scale, whole number */
int scale_val1; /* scale, fraction in micros */
int scale_val1; /* scale, fraction in nanos */
} 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_UNITS_METERS_PER_SEC_SQRD, 1, 0},
{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_UNITS_RADIANS_PER_SECOND, 1, 0},
{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_INCLINOMETER_3D, 0, 0, 17453},
{HID_USAGE_SENSOR_INCLINOMETER_3D, 0, 0, 17453293},
{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_UNITS_RADIANS, 1, 0},
@ -57,7 +57,7 @@ static struct {
{HID_USAGE_SENSOR_ALS, HID_USAGE_SENSOR_UNITS_LUX, 1, 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)
@ -266,15 +266,15 @@ EXPORT_SYMBOL(hid_sensor_write_raw_hyst_value);
/*
* This fuction applies the unit exponent to the scale.
* For example:
* 9.806650 ->exp:2-> val0[980]val1[665000]
* 9.000806 ->exp:2-> val0[900]val1[80600]
* 0.174535 ->exp:2-> val0[17]val1[453500]
* 1.001745 ->exp:0-> val0[1]val1[1745]
* 1.001745 ->exp:2-> val0[100]val1[174500]
* 1.001745 ->exp:4-> val0[10017]val1[450000]
* 9.806650 ->exp:-2-> val0[0]val1[98066]
* 9.806650000 ->exp:2-> val0[980]val1[665000000]
* 9.000806000 ->exp:2-> val0[900]val1[80600000]
* 0.174535293 ->exp:2-> val0[17]val1[453529300]
* 1.001745329 ->exp:0-> val0[1]val1[1745329]
* 1.001745329 ->exp:2-> val0[100]val1[174532900]
* 1.001745329 ->exp:4-> val0[10017]val1[453290000]
* 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 i;
@ -285,32 +285,32 @@ static void adjust_exponent_micro(int *val0, int *val1, int scale0,
if (exp > 0) {
*val0 = scale0 * pow_10(exp);
res = 0;
if (exp > 6) {
if (exp > 9) {
*val1 = 0;
return;
}
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);
scale1 = scale1 % pow_10(5 - i);
scale1 = scale1 % pow_10(8 - i);
}
*val0 += res;
*val1 = scale1 * pow_10(exp);
} else if (exp < 0) {
exp = abs(exp);
if (exp > 6) {
if (exp > 9) {
*val0 = *val1 = 0;
return;
}
*val0 = scale0 / pow_10(exp);
rem = scale0 % pow_10(exp);
res = 0;
for (i = 0; i < (6 - exp); ++i) {
x = scale1 / pow_10(5 - i);
res += (pow_10(5 - exp - i) * x);
scale1 = scale1 % pow_10(5 - i);
for (i = 0; i < (9 - exp); ++i) {
x = scale1 / pow_10(8 - i);
res += (pow_10(8 - exp - i) * x);
scale1 = scale1 % pow_10(8 - i);
}
*val1 = rem * pow_10(6 - exp) + res;
*val1 = rem * pow_10(9 - exp) + res;
} else {
*val0 = scale0;
*val1 = scale1;
@ -332,14 +332,14 @@ int hid_sensor_format_scale(u32 usage_id,
unit_conversion[i].unit == attr_info->units) {
exp = hid_sensor_convert_exponent(
attr_info->unit_expo);
adjust_exponent_micro(val0, val1,
adjust_exponent_nano(val0, val1,
unit_conversion[i].scale_val0,
unit_conversion[i].scale_val1, exp);
break;
}
}
return IIO_VAL_INT_PLUS_MICRO;
return IIO_VAL_INT_PLUS_NANO;
}
EXPORT_SYMBOL(hid_sensor_format_scale);

View file

@ -612,7 +612,7 @@ EXPORT_SYMBOL(st_sensors_sysfs_sampling_frequency_avail);
ssize_t st_sensors_sysfs_scale_avail(struct device *dev,
struct device_attribute *attr, char *buf)
{
int i, len = 0;
int i, len = 0, q, r;
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct st_sensor_data *sdata = iio_priv(indio_dev);
@ -621,8 +621,10 @@ ssize_t st_sensors_sysfs_scale_avail(struct device *dev,
if (sdata->sensor_settings->fs.fs_avl[i].num == 0)
break;
len += scnprintf(buf + len, PAGE_SIZE - len, "0.%06u ",
sdata->sensor_settings->fs.fs_avl[i].gain);
q = sdata->sensor_settings->fs.fs_avl[i].gain / 1000000;
r = sdata->sensor_settings->fs.fs_avl[i].gain % 1000000;
len += scnprintf(buf + len, PAGE_SIZE - len, "%u.%06u ", q, r);
}
mutex_unlock(&indio_dev->mlock);
buf[len - 1] = '\n';

View file

@ -335,6 +335,7 @@ static struct platform_driver hid_dev_rot_platform_driver = {
.id_table = hid_dev_rot_ids,
.driver = {
.name = KBUILD_MODNAME,
.pm = &hid_sensor_pm_ops,
},
.probe = hid_dev_rot_probe,
.remove = hid_dev_rot_remove,

View file

@ -655,6 +655,7 @@ static void ad5933_work(struct work_struct *work)
__be16 buf[2];
int val[2];
unsigned char status;
int ret;
mutex_lock(&indio_dev->mlock);
if (st->state == AD5933_CTRL_INIT_START_FREQ) {
@ -662,19 +663,22 @@ static void ad5933_work(struct work_struct *work)
ad5933_cmd(st, AD5933_CTRL_START_SWEEP);
st->state = AD5933_CTRL_START_SWEEP;
schedule_delayed_work(&st->work, st->poll_time_jiffies);
mutex_unlock(&indio_dev->mlock);
return;
goto out;
}
ad5933_i2c_read(st->client, AD5933_REG_STATUS, 1, &status);
ret = ad5933_i2c_read(st->client, AD5933_REG_STATUS, 1, &status);
if (ret)
goto out;
if (status & AD5933_STAT_DATA_VALID) {
int scan_count = bitmap_weight(indio_dev->active_scan_mask,
indio_dev->masklength);
ad5933_i2c_read(st->client,
ret = ad5933_i2c_read(st->client,
test_bit(1, indio_dev->active_scan_mask) ?
AD5933_REG_REAL_DATA : AD5933_REG_IMAG_DATA,
scan_count * 2, (u8 *)buf);
if (ret)
goto out;
if (scan_count == 2) {
val[0] = be16_to_cpu(buf[0]);
@ -686,8 +690,7 @@ static void ad5933_work(struct work_struct *work)
} else {
/* no data available - try again later */
schedule_delayed_work(&st->work, st->poll_time_jiffies);
mutex_unlock(&indio_dev->mlock);
return;
goto out;
}
if (status & AD5933_STAT_SWEEP_DONE) {
@ -700,7 +703,7 @@ static void ad5933_work(struct work_struct *work)
ad5933_cmd(st, AD5933_CTRL_INC_FREQ);
schedule_delayed_work(&st->work, st->poll_time_jiffies);
}
out:
mutex_unlock(&indio_dev->mlock);
}