Commit 371c6d97 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge tag 'iio-fixes-for-4.9b' of...

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.
parents a909d3e6 6f77199e
...@@ -743,8 +743,8 @@ static int st_accel_read_raw(struct iio_dev *indio_dev, ...@@ -743,8 +743,8 @@ static int st_accel_read_raw(struct iio_dev *indio_dev,
return IIO_VAL_INT; return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE: case IIO_CHAN_INFO_SCALE:
*val = 0; *val = adata->current_fullscale->gain / 1000000;
*val2 = adata->current_fullscale->gain; *val2 = adata->current_fullscale->gain % 1000000;
return IIO_VAL_INT_PLUS_MICRO; return IIO_VAL_INT_PLUS_MICRO;
case IIO_CHAN_INFO_SAMP_FREQ: case IIO_CHAN_INFO_SAMP_FREQ:
*val = adata->odr; *val = adata->odr;
...@@ -763,9 +763,13 @@ static int st_accel_write_raw(struct iio_dev *indio_dev, ...@@ -763,9 +763,13 @@ static int st_accel_write_raw(struct iio_dev *indio_dev,
int err; int err;
switch (mask) { switch (mask) {
case IIO_CHAN_INFO_SCALE: case IIO_CHAN_INFO_SCALE: {
err = st_sensors_set_fullscale_by_gain(indio_dev, val2); int gain;
gain = val * 1000000 + val2;
err = st_sensors_set_fullscale_by_gain(indio_dev, gain);
break; break;
}
case IIO_CHAN_INFO_SAMP_FREQ: case IIO_CHAN_INFO_SAMP_FREQ:
if (val2) if (val2)
return -EINVAL; return -EINVAL;
......
...@@ -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);
......
...@@ -612,7 +612,7 @@ EXPORT_SYMBOL(st_sensors_sysfs_sampling_frequency_avail); ...@@ -612,7 +612,7 @@ EXPORT_SYMBOL(st_sensors_sysfs_sampling_frequency_avail);
ssize_t st_sensors_sysfs_scale_avail(struct device *dev, ssize_t st_sensors_sysfs_scale_avail(struct device *dev,
struct device_attribute *attr, char *buf) 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 iio_dev *indio_dev = dev_get_drvdata(dev);
struct st_sensor_data *sdata = iio_priv(indio_dev); struct st_sensor_data *sdata = iio_priv(indio_dev);
...@@ -621,8 +621,10 @@ ssize_t st_sensors_sysfs_scale_avail(struct device *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) if (sdata->sensor_settings->fs.fs_avl[i].num == 0)
break; break;
len += scnprintf(buf + len, PAGE_SIZE - len, "0.%06u ", q = sdata->sensor_settings->fs.fs_avl[i].gain / 1000000;
sdata->sensor_settings->fs.fs_avl[i].gain); 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); mutex_unlock(&indio_dev->mlock);
buf[len - 1] = '\n'; buf[len - 1] = '\n';
......
...@@ -335,6 +335,7 @@ static struct platform_driver hid_dev_rot_platform_driver = { ...@@ -335,6 +335,7 @@ static struct platform_driver hid_dev_rot_platform_driver = {
.id_table = hid_dev_rot_ids, .id_table = hid_dev_rot_ids,
.driver = { .driver = {
.name = KBUILD_MODNAME, .name = KBUILD_MODNAME,
.pm = &hid_sensor_pm_ops,
}, },
.probe = hid_dev_rot_probe, .probe = hid_dev_rot_probe,
.remove = hid_dev_rot_remove, .remove = hid_dev_rot_remove,
......
...@@ -655,6 +655,7 @@ static void ad5933_work(struct work_struct *work) ...@@ -655,6 +655,7 @@ static void ad5933_work(struct work_struct *work)
__be16 buf[2]; __be16 buf[2];
int val[2]; int val[2];
unsigned char status; unsigned char status;
int ret;
mutex_lock(&indio_dev->mlock); mutex_lock(&indio_dev->mlock);
if (st->state == AD5933_CTRL_INIT_START_FREQ) { if (st->state == AD5933_CTRL_INIT_START_FREQ) {
...@@ -662,19 +663,22 @@ static void ad5933_work(struct work_struct *work) ...@@ -662,19 +663,22 @@ static void ad5933_work(struct work_struct *work)
ad5933_cmd(st, AD5933_CTRL_START_SWEEP); ad5933_cmd(st, AD5933_CTRL_START_SWEEP);
st->state = AD5933_CTRL_START_SWEEP; st->state = AD5933_CTRL_START_SWEEP;
schedule_delayed_work(&st->work, st->poll_time_jiffies); schedule_delayed_work(&st->work, st->poll_time_jiffies);
mutex_unlock(&indio_dev->mlock); goto out;
return;
} }
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) { if (status & AD5933_STAT_DATA_VALID) {
int scan_count = bitmap_weight(indio_dev->active_scan_mask, int scan_count = bitmap_weight(indio_dev->active_scan_mask,
indio_dev->masklength); indio_dev->masklength);
ad5933_i2c_read(st->client, ret = ad5933_i2c_read(st->client,
test_bit(1, indio_dev->active_scan_mask) ? test_bit(1, indio_dev->active_scan_mask) ?
AD5933_REG_REAL_DATA : AD5933_REG_IMAG_DATA, AD5933_REG_REAL_DATA : AD5933_REG_IMAG_DATA,
scan_count * 2, (u8 *)buf); scan_count * 2, (u8 *)buf);
if (ret)
goto out;
if (scan_count == 2) { if (scan_count == 2) {
val[0] = be16_to_cpu(buf[0]); val[0] = be16_to_cpu(buf[0]);
...@@ -686,8 +690,7 @@ static void ad5933_work(struct work_struct *work) ...@@ -686,8 +690,7 @@ static void ad5933_work(struct work_struct *work)
} else { } else {
/* no data available - try again later */ /* no data available - try again later */
schedule_delayed_work(&st->work, st->poll_time_jiffies); schedule_delayed_work(&st->work, st->poll_time_jiffies);
mutex_unlock(&indio_dev->mlock); goto out;
return;
} }
if (status & AD5933_STAT_SWEEP_DONE) { if (status & AD5933_STAT_SWEEP_DONE) {
...@@ -700,7 +703,7 @@ static void ad5933_work(struct work_struct *work) ...@@ -700,7 +703,7 @@ static void ad5933_work(struct work_struct *work)
ad5933_cmd(st, AD5933_CTRL_INC_FREQ); ad5933_cmd(st, AD5933_CTRL_INC_FREQ);
schedule_delayed_work(&st->work, st->poll_time_jiffies); schedule_delayed_work(&st->work, st->poll_time_jiffies);
} }
out:
mutex_unlock(&indio_dev->mlock); mutex_unlock(&indio_dev->mlock);
} }
......
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