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: abeb6b1e7b ("iio: magnetometer: Add support for MEMSIC MMC35240") Signed-off-by: Daniel Baluta <daniel.baluta@intel.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
This commit is contained in:
parent
bd35a214f5
commit
c2890547a0
@ -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])
|
|||||||
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,
|
|||||||
|
|
||||||
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,
|
|||||||
__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);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user