diff --git a/drivers/iio/accel/hid-sensor-accel-3d.c b/drivers/iio/accel/hid-sensor-accel-3d.c index 39de79ce8778de81441029690f047db1b9639fe3..ca5759c0c318eb807baf14cb09a1a6b5f3c1b748 100644 --- a/drivers/iio/accel/hid-sensor-accel-3d.c +++ b/drivers/iio/accel/hid-sensor-accel-3d.c @@ -93,6 +93,41 @@ static const struct iio_chan_spec accel_3d_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(3) }; +/* Channel definitions */ +static const struct iio_chan_spec gravity_channels[] = { + { + .type = IIO_GRAVITY, + .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) | + BIT(IIO_CHAN_INFO_HYSTERESIS), + .scan_index = CHANNEL_SCAN_INDEX_X, + }, { + .type = IIO_GRAVITY, + .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) | + BIT(IIO_CHAN_INFO_HYSTERESIS), + .scan_index = CHANNEL_SCAN_INDEX_Y, + }, { + .type = IIO_GRAVITY, + .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) | + BIT(IIO_CHAN_INFO_HYSTERESIS), + .scan_index = CHANNEL_SCAN_INDEX_Z, + } +}; + /* Adjust channel real bits based on report descriptor */ static void accel_3d_adjust_channel_bit_mask(struct iio_chan_spec *channels, int channel, int size) @@ -114,6 +149,8 @@ static int accel_3d_read_raw(struct iio_dev *indio_dev, int report_id = -1; u32 address; int ret_type; + struct hid_sensor_hub_device *hsdev = + accel_state->common_attributes.hsdev; *val = 0; *val2 = 0; @@ -125,8 +162,7 @@ static int accel_3d_read_raw(struct iio_dev *indio_dev, 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, + hsdev->usage, address, report_id, SENSOR_HUB_SYNC); else { *val = 0; @@ -288,7 +324,7 @@ static int accel_3d_parse_report(struct platform_device *pdev, st->accel[2].index, st->accel[2].report_id); st->scale_precision = hid_sensor_format_scale( - HID_USAGE_SENSOR_ACCEL_3D, + hsdev->usage, &st->accel[CHANNEL_SCAN_INDEX_X], &st->scale_pre_decml, &st->scale_post_decml); @@ -311,9 +347,12 @@ static int accel_3d_parse_report(struct platform_device *pdev, static int hid_accel_3d_probe(struct platform_device *pdev) { int ret = 0; - static const char *name = "accel_3d"; + static const char *name; struct iio_dev *indio_dev; struct accel_3d_state *accel_state; + const struct iio_chan_spec *channel_spec; + int channel_size; + struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data; indio_dev = devm_iio_device_alloc(&pdev->dev, @@ -327,24 +366,30 @@ static int hid_accel_3d_probe(struct platform_device *pdev) accel_state->common_attributes.hsdev = hsdev; accel_state->common_attributes.pdev = pdev; - ret = hid_sensor_parse_common_attributes(hsdev, - HID_USAGE_SENSOR_ACCEL_3D, + if (hsdev->usage == HID_USAGE_SENSOR_ACCEL_3D) { + name = "accel_3d"; + channel_spec = accel_3d_channels; + channel_size = sizeof(accel_3d_channels); + } else { + name = "gravity"; + channel_spec = gravity_channels; + channel_size = sizeof(gravity_channels); + } + ret = hid_sensor_parse_common_attributes(hsdev, hsdev->usage, &accel_state->common_attributes); if (ret) { dev_err(&pdev->dev, "failed to setup common attributes\n"); return ret; } + indio_dev->channels = kmemdup(channel_spec, channel_size, GFP_KERNEL); - indio_dev->channels = kmemdup(accel_3d_channels, - sizeof(accel_3d_channels), GFP_KERNEL); if (!indio_dev->channels) { dev_err(&pdev->dev, "failed to duplicate channels\n"); return -ENOMEM; } - ret = accel_3d_parse_report(pdev, hsdev, - (struct iio_chan_spec *)indio_dev->channels, - HID_USAGE_SENSOR_ACCEL_3D, accel_state); + (struct iio_chan_spec *)indio_dev->channels, + hsdev->usage, accel_state); if (ret) { dev_err(&pdev->dev, "failed to setup attributes\n"); goto error_free_dev_mem; @@ -379,7 +424,7 @@ static int hid_accel_3d_probe(struct platform_device *pdev) accel_state->callbacks.send_event = accel_3d_proc_event; accel_state->callbacks.capture_sample = accel_3d_capture_sample; accel_state->callbacks.pdev = pdev; - ret = sensor_hub_register_callback(hsdev, HID_USAGE_SENSOR_ACCEL_3D, + ret = sensor_hub_register_callback(hsdev, hsdev->usage, &accel_state->callbacks); if (ret < 0) { dev_err(&pdev->dev, "callback reg failed\n"); @@ -406,7 +451,7 @@ static int hid_accel_3d_remove(struct platform_device *pdev) struct iio_dev *indio_dev = platform_get_drvdata(pdev); struct accel_3d_state *accel_state = iio_priv(indio_dev); - sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_ACCEL_3D); + sensor_hub_remove_callback(hsdev, hsdev->usage); iio_device_unregister(indio_dev); hid_sensor_remove_trigger(&accel_state->common_attributes); iio_triggered_buffer_cleanup(indio_dev); @@ -420,6 +465,9 @@ static const struct platform_device_id hid_accel_3d_ids[] = { /* Format: HID-SENSOR-usage_id_in_hex_lowercase */ .name = "HID-SENSOR-200073", }, + { /* gravity sensor */ + .name = "HID-SENSOR-20007b", + }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(platform, hid_accel_3d_ids); diff --git a/include/linux/hid-sensor-ids.h b/include/linux/hid-sensor-ids.h index 9a3a9db1b39d15f5864c69c0142c03327b266c56..30c7dc45e45fcc0110dfaae19ff69d523621414b 100644 --- a/include/linux/hid-sensor-ids.h +++ b/include/linux/hid-sensor-ids.h @@ -52,6 +52,9 @@ #define HID_USAGE_SENSOR_ANGL_VELOCITY_Y_AXIS 0x200458 #define HID_USAGE_SENSOR_ANGL_VELOCITY_Z_AXIS 0x200459 +/* Gravity vector */ +#define HID_USAGE_SENSOR_GRAVITY_VECTOR 0x20007B + /* ORIENTATION: Compass 3D: (200083) */ #define HID_USAGE_SENSOR_COMPASS_3D 0x200083 #define HID_USAGE_SENSOR_DATA_ORIENTATION 0x200470