diff options
Diffstat (limited to 'drivers/iio/accel/hid-sensor-accel-3d.c')
-rw-r--r-- | drivers/iio/accel/hid-sensor-accel-3d.c | 45 |
1 files changed, 34 insertions, 11 deletions
diff --git a/drivers/iio/accel/hid-sensor-accel-3d.c b/drivers/iio/accel/hid-sensor-accel-3d.c index 3dcdbad65456..69abf9163df7 100644 --- a/drivers/iio/accel/hid-sensor-accel-3d.c +++ b/drivers/iio/accel/hid-sensor-accel-3d.c @@ -22,6 +22,7 @@ #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/slab.h> +#include <linux/delay.h> #include <linux/hid-sensor-hub.h> #include <linux/iio/iio.h> #include <linux/iio/sysfs.h> @@ -42,6 +43,10 @@ struct accel_3d_state { struct hid_sensor_common common_attributes; struct hid_sensor_hub_attribute_info accel[ACCEL_3D_CHANNEL_MAX]; u32 accel_val[ACCEL_3D_CHANNEL_MAX]; + int scale_pre_decml; + int scale_post_decml; + int scale_precision; + int value_offset; }; static const u32 accel_3d_addresses[ACCEL_3D_CHANNEL_MAX] = { @@ -56,6 +61,7 @@ static const struct iio_chan_spec accel_3d_channels[] = { .type = IIO_ACCEL, .modified = 1, .channel2 = IIO_MOD_X, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_SAMP_FREQ) | @@ -65,6 +71,7 @@ static const struct iio_chan_spec accel_3d_channels[] = { .type = IIO_ACCEL, .modified = 1, .channel2 = IIO_MOD_Y, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_SAMP_FREQ) | @@ -74,6 +81,7 @@ static const struct iio_chan_spec accel_3d_channels[] = { .type = IIO_ACCEL, .modified = 1, .channel2 = IIO_MOD_Z, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_SAMP_FREQ) | @@ -104,31 +112,42 @@ static int accel_3d_read_raw(struct iio_dev *indio_dev, u32 address; int ret; int ret_type; + s32 poll_value; *val = 0; *val2 = 0; switch (mask) { case 0: + poll_value = hid_sensor_read_poll_value( + &accel_state->common_attributes); + if (poll_value < 0) + return -EINVAL; + + hid_sensor_power_state(&accel_state->common_attributes, true); + msleep_interruptible(poll_value * 2); report_id = accel_state->accel[chan->scan_index].report_id; address = accel_3d_addresses[chan->scan_index]; if (report_id >= 0) *val = sensor_hub_input_attr_get_raw_value( - accel_state->common_attributes.hsdev, - HID_USAGE_SENSOR_ACCEL_3D, address, - report_id); + accel_state->common_attributes.hsdev, + HID_USAGE_SENSOR_ACCEL_3D, address, + report_id); else { *val = 0; + hid_sensor_power_state(&accel_state->common_attributes, + false); return -EINVAL; } + hid_sensor_power_state(&accel_state->common_attributes, false); ret_type = IIO_VAL_INT; break; case IIO_CHAN_INFO_SCALE: - *val = accel_state->accel[CHANNEL_SCAN_INDEX_X].units; - ret_type = IIO_VAL_INT; + *val = accel_state->scale_pre_decml; + *val2 = accel_state->scale_post_decml; + ret_type = accel_state->scale_precision; break; case IIO_CHAN_INFO_OFFSET: - *val = hid_sensor_convert_exponent( - accel_state->accel[CHANNEL_SCAN_INDEX_X].unit_expo); + *val = accel_state->value_offset; ret_type = IIO_VAL_INT; break; case IIO_CHAN_INFO_SAMP_FREQ: @@ -197,9 +216,8 @@ static int accel_3d_proc_event(struct hid_sensor_hub_device *hsdev, struct iio_dev *indio_dev = platform_get_drvdata(priv); struct accel_3d_state *accel_state = iio_priv(indio_dev); - dev_dbg(&indio_dev->dev, "accel_3d_proc_event [%d]\n", - accel_state->common_attributes.data_ready); - if (accel_state->common_attributes.data_ready) + dev_dbg(&indio_dev->dev, "accel_3d_proc_event\n"); + if (atomic_read(&accel_state->common_attributes.data_ready)) hid_sensor_push_data(indio_dev, accel_state->accel_val, sizeof(accel_state->accel_val)); @@ -262,6 +280,11 @@ static int accel_3d_parse_report(struct platform_device *pdev, st->accel[1].index, st->accel[1].report_id, st->accel[2].index, st->accel[2].report_id); + st->scale_precision = hid_sensor_format_scale( + HID_USAGE_SENSOR_ACCEL_3D, + &st->accel[CHANNEL_SCAN_INDEX_X], + &st->scale_pre_decml, &st->scale_post_decml); + /* Set Sensitivity field ids, when there is no individual modifier */ if (st->common_attributes.sensitivity.index < 0) { sensor_hub_input_get_attribute_info(hsdev, @@ -333,7 +356,7 @@ static int hid_accel_3d_probe(struct platform_device *pdev) dev_err(&pdev->dev, "failed to initialize trigger buffer\n"); goto error_free_dev_mem; } - accel_state->common_attributes.data_ready = false; + atomic_set(&accel_state->common_attributes.data_ready, 0); ret = hid_sensor_setup_trigger(indio_dev, name, &accel_state->common_attributes); if (ret < 0) { |