iio: cros_ec: Add calibscale for 3d MEMS
authorGwendal Grignou <gwendal@chromium.org>
Thu, 18 Jul 2019 23:28:24 +0000 (16:28 -0700)
committerJonathan Cameron <Jonathan.Cameron@huawei.com>
Sat, 27 Jul 2019 19:11:18 +0000 (20:11 +0100)
Add calibration scale support to accel, gyro and magnetometer.

Check on eve with current firmware, check reading calibscale returns 1.0,
check with newer firmware values are applied.

Signed-off-by: Gwendal Grignou <gwendal@chromium.org>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
drivers/iio/light/cros_ec_light_prox.c
drivers/iio/pressure/cros_ec_baro.c
include/linux/iio/common/cros_ec_sensors_core.h

index 17af4e0..2af0960 100644 (file)
@@ -63,10 +63,35 @@ static int cros_ec_sensors_read(struct iio_dev *indio_dev,
 
                /* Save values */
                for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++)
-                       st->core.calib[i] =
+                       st->core.calib[i].offset =
                                st->core.resp->sensor_offset.offset[i];
                ret = IIO_VAL_INT;
-               *val = st->core.calib[idx];
+               *val = st->core.calib[idx].offset;
+               break;
+       case IIO_CHAN_INFO_CALIBSCALE:
+               st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_SCALE;
+               st->core.param.sensor_offset.flags = 0;
+
+               ret = cros_ec_motion_send_host_cmd(&st->core, 0);
+               if (ret == -EPROTO) {
+                       /* Reading calibscale is not supported on older EC. */
+                       *val = 1;
+                       *val2 = 0;
+                       ret = IIO_VAL_INT_PLUS_MICRO;
+                       break;
+               } else if (ret) {
+                       break;
+               }
+
+               /* Save values */
+               for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++)
+                       st->core.calib[i].scale =
+                               st->core.resp->sensor_scale.scale[i];
+
+               *val = st->core.calib[idx].scale >> 15;
+               *val2 = ((st->core.calib[idx].scale & 0x7FFF) * 1000000LL) /
+                       MOTION_SENSE_DEFAULT_SCALE;
+               ret = IIO_VAL_INT_PLUS_MICRO;
                break;
        case IIO_CHAN_INFO_SCALE:
                st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_RANGE;
@@ -134,7 +159,7 @@ static int cros_ec_sensors_write(struct iio_dev *indio_dev,
 
        switch (mask) {
        case IIO_CHAN_INFO_CALIBBIAS:
-               st->core.calib[idx] = val;
+               st->core.calib[idx].offset = val;
 
                /* Send to EC for each axis, even if not complete */
                st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_OFFSET;
@@ -142,12 +167,27 @@ static int cros_ec_sensors_write(struct iio_dev *indio_dev,
                        MOTION_SENSE_SET_OFFSET;
                for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++)
                        st->core.param.sensor_offset.offset[i] =
-                               st->core.calib[i];
+                               st->core.calib[i].offset;
                st->core.param.sensor_offset.temp =
                        EC_MOTION_SENSE_INVALID_CALIB_TEMP;
 
                ret = cros_ec_motion_send_host_cmd(&st->core, 0);
                break;
+       case IIO_CHAN_INFO_CALIBSCALE:
+               st->core.calib[idx].scale = val;
+               /* Send to EC for each axis, even if not complete */
+
+               st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_SCALE;
+               st->core.param.sensor_offset.flags =
+                       MOTION_SENSE_SET_OFFSET;
+               for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++)
+                       st->core.param.sensor_scale.scale[i] =
+                               st->core.calib[i].scale;
+               st->core.param.sensor_scale.temp =
+                       EC_MOTION_SENSE_INVALID_CALIB_TEMP;
+
+               ret = cros_ec_motion_send_host_cmd(&st->core, 0);
+               break;
        case IIO_CHAN_INFO_SCALE:
                if (st->core.type == MOTIONSENSE_TYPE_MAG) {
                        ret = -EINVAL;
@@ -206,7 +246,8 @@ static int cros_ec_sensors_probe(struct platform_device *pdev)
                /* Common part */
                channel->info_mask_separate =
                        BIT(IIO_CHAN_INFO_RAW) |
-                       BIT(IIO_CHAN_INFO_CALIBBIAS);
+                       BIT(IIO_CHAN_INFO_CALIBBIAS) |
+                       BIT(IIO_CHAN_INFO_CALIBSCALE);
                channel->info_mask_shared_by_all =
                        BIT(IIO_CHAN_INFO_SCALE) |
                        BIT(IIO_CHAN_INFO_FREQUENCY) |
index 130362c..96d5aa1 100644 (file)
@@ -118,7 +118,7 @@ static ssize_t cros_ec_sensors_calibrate(struct iio_dev *indio_dev,
        } else {
                /* Save values */
                for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++)
-                       st->calib[i] = st->resp->perform_calib.offset[i];
+                       st->calib[i].offset = st->resp->perform_calib.offset[i];
        }
        mutex_unlock(&st->cmd_lock);
 
index 308ee6f..b81746a 100644 (file)
@@ -88,9 +88,10 @@ static int cros_ec_light_prox_read(struct iio_dev *indio_dev,
                }
 
                /* Save values */
-               st->core.calib[0] = st->core.resp->sensor_offset.offset[0];
+               st->core.calib[0].offset =
+                       st->core.resp->sensor_offset.offset[0];
 
-               *val = st->core.calib[idx];
+               *val = st->core.calib[idx].offset;
                break;
        case IIO_CHAN_INFO_CALIBSCALE:
                /*
@@ -134,11 +135,12 @@ static int cros_ec_light_prox_write(struct iio_dev *indio_dev,
 
        switch (mask) {
        case IIO_CHAN_INFO_CALIBBIAS:
-               st->core.calib[idx] = val;
+               st->core.calib[idx].offset = val;
                /* Send to EC for each axis, even if not complete */
                st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_OFFSET;
                st->core.param.sensor_offset.flags = MOTION_SENSE_SET_OFFSET;
-               st->core.param.sensor_offset.offset[0] = st->core.calib[0];
+               st->core.param.sensor_offset.offset[0] =
+                       st->core.calib[0].offset;
                st->core.param.sensor_offset.temp =
                                        EC_MOTION_SENSE_INVALID_CALIB_TEMP;
                if (cros_ec_motion_send_host_cmd(&st->core, 0))
@@ -205,8 +207,6 @@ static int cros_ec_light_prox_probe(struct platform_device *pdev)
        channel->ext_info = cros_ec_sensors_ext_info;
        channel->scan_type.sign = 'u';
 
-       state->core.calib[0] = 0;
-
        /* Sensor specific */
        switch (state->core.type) {
        case MOTIONSENSE_TYPE_LIGHT:
index 034ce98..d3acba7 100644 (file)
@@ -152,8 +152,6 @@ static int cros_ec_baro_probe(struct platform_device *pdev)
        channel->ext_info = cros_ec_sensors_ext_info;
        channel->scan_type.sign = 'u';
 
-       state->core.calib[0] = 0;
-
        /* Sensor specific */
        switch (state->core.type) {
        case MOTIONSENSE_TYPE_BARO:
index 0c636b9..bb03a25 100644 (file)
@@ -62,7 +62,10 @@ struct cros_ec_sensors_core_state {
        enum motionsensor_type type;
        enum motionsensor_location loc;
 
-       s16 calib[CROS_EC_SENSOR_MAX_AXIS];
+       struct calib_data {
+               s16 offset;
+               u16 scale;
+       } calib[CROS_EC_SENSOR_MAX_AXIS];
 
        u8 samples[CROS_EC_SAMPLE_SIZE];