Commit c2890547 authored by Daniel Baluta's avatar Daniel Baluta Committed by Jonathan Cameron

iio: magnetometer: mmc35240: Fix broken processed value

The current computation for fractional part of the magnetic
field is broken. This patch fixes it by taking a different
approach. We expose the raw reading in milli Gauss (to avoid
rounding errors) with a scale of 0.001.

Thus the final computation is done in userspace where floating
point operation are more relaxed.

Fixes: abeb6b1e ("iio: magnetometer: Add support for MEMSIC MMC35240")
Signed-off-by: default avatarDaniel Baluta <daniel.baluta@intel.com>
Signed-off-by: default avatarJonathan Cameron <jic23@kernel.org>
parent bd35a214
...@@ -113,8 +113,9 @@ static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("100 200 333 666"); ...@@ -113,8 +113,9 @@ static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("100 200 333 666");
.modified = 1, \ .modified = 1, \
.channel2 = IIO_MOD_ ## _axis, \ .channel2 = IIO_MOD_ ## _axis, \
.address = AXIS_ ## _axis, \ .address = AXIS_ ## _axis, \
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), \ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
BIT(IIO_CHAN_INFO_SCALE), \
} }
static const struct iio_chan_spec mmc35240_channels[] = { static const struct iio_chan_spec mmc35240_channels[] = {
...@@ -241,9 +242,19 @@ static int mmc35240_read_measurement(struct mmc35240_data *data, __le16 buf[3]) ...@@ -241,9 +242,19 @@ static int mmc35240_read_measurement(struct mmc35240_data *data, __le16 buf[3])
3 * sizeof(__le16)); 3 * sizeof(__le16));
} }
static int mmc35240_raw_to_gauss(struct mmc35240_data *data, int index, /**
__le16 buf[], * mmc35240_raw_to_mgauss - convert raw readings to milli gauss. Also apply
int *val, int *val2) compensation for output value.
*
* @data: device private data
* @index: axis index for which we want the conversion
* @buf: raw data to be converted, 2 bytes in little endian format
* @val: compensated output reading (unit is milli gauss)
*
* Returns: 0 in case of success, -EINVAL when @index is not valid
*/
static int mmc35240_raw_to_mgauss(struct mmc35240_data *data, int index,
__le16 buf[], int *val)
{ {
int raw_x, raw_y, raw_z; int raw_x, raw_y, raw_z;
int sens_x, sens_y, sens_z; int sens_x, sens_y, sens_z;
...@@ -261,18 +272,15 @@ static int mmc35240_raw_to_gauss(struct mmc35240_data *data, int index, ...@@ -261,18 +272,15 @@ static int mmc35240_raw_to_gauss(struct mmc35240_data *data, int index,
switch (index) { switch (index) {
case AXIS_X: case AXIS_X:
*val = (raw_x - nfo) / sens_x; *val = (raw_x - nfo) * 1000 / sens_x;
*val2 = ((raw_x - nfo) % sens_x) * 1000000;
break; break;
case AXIS_Y: case AXIS_Y:
*val = (raw_y - nfo) / sens_y - (raw_z - nfo) / sens_z; *val = (raw_y - nfo) * 1000 / sens_y -
*val2 = (((raw_y - nfo) % sens_y - (raw_z - nfo) % sens_z)) (raw_z - nfo) * 1000 / sens_z;
* 1000000;
break; break;
case AXIS_Z: case AXIS_Z:
*val = (raw_y - nfo) / sens_y + (raw_z - nfo) / sens_z; *val = (raw_y - nfo) * 1000 / sens_y +
*val2 = (((raw_y - nfo) % sens_y + (raw_z - nfo) % sens_z)) (raw_z - nfo) * 1000 / sens_z;
* 1000000;
break; break;
default: default:
return -EINVAL; return -EINVAL;
...@@ -290,16 +298,19 @@ static int mmc35240_read_raw(struct iio_dev *indio_dev, ...@@ -290,16 +298,19 @@ static int mmc35240_read_raw(struct iio_dev *indio_dev,
__le16 buf[3]; __le16 buf[3];
switch (mask) { switch (mask) {
case IIO_CHAN_INFO_PROCESSED: case IIO_CHAN_INFO_RAW:
mutex_lock(&data->mutex); mutex_lock(&data->mutex);
ret = mmc35240_read_measurement(data, buf); ret = mmc35240_read_measurement(data, buf);
mutex_unlock(&data->mutex); mutex_unlock(&data->mutex);
if (ret < 0) if (ret < 0)
return ret; return ret;
ret = mmc35240_raw_to_gauss(data, chan->address, ret = mmc35240_raw_to_mgauss(data, chan->address, buf, val);
buf, val, val2);
if (ret < 0) if (ret < 0)
return ret; return ret;
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
*val = 0;
*val2 = 1000;
return IIO_VAL_INT_PLUS_MICRO; return IIO_VAL_INT_PLUS_MICRO;
case IIO_CHAN_INFO_SAMP_FREQ: case IIO_CHAN_INFO_SAMP_FREQ:
mutex_lock(&data->mutex); mutex_lock(&data->mutex);
......
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