diff options
Diffstat (limited to 'drivers/iio/light/hid-sensor-als.c')
-rw-r--r-- | drivers/iio/light/hid-sensor-als.c | 107 |
1 files changed, 52 insertions, 55 deletions
diff --git a/drivers/iio/light/hid-sensor-als.c b/drivers/iio/light/hid-sensor-als.c index b6cd299517d1..5a1a625d8d16 100644 --- a/drivers/iio/light/hid-sensor-als.c +++ b/drivers/iio/light/hid-sensor-als.c @@ -6,16 +6,11 @@ #include <linux/device.h> #include <linux/platform_device.h> #include <linux/module.h> -#include <linux/interrupt.h> -#include <linux/irq.h> +#include <linux/mod_devicetable.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> #include <linux/iio/buffer.h> -#include <linux/iio/trigger_consumer.h> -#include <linux/iio/triggered_buffer.h> #include "../common/hid-sensors/hid-sensor-trigger.h" enum { @@ -24,15 +19,26 @@ enum { CHANNEL_SCAN_INDEX_MAX }; +#define CHANNEL_SCAN_INDEX_TIMESTAMP CHANNEL_SCAN_INDEX_MAX + struct als_state { struct hid_sensor_hub_callbacks callbacks; struct hid_sensor_common common_attributes; struct hid_sensor_hub_attribute_info als_illum; - u32 illum[CHANNEL_SCAN_INDEX_MAX]; + struct { + u32 illum[CHANNEL_SCAN_INDEX_MAX]; + u64 timestamp __aligned(8); + } scan; int scale_pre_decml; int scale_post_decml; int scale_precision; int value_offset; + s64 timestamp; +}; + +static const u32 als_sensitivity_addresses[] = { + HID_USAGE_SENSOR_DATA_LIGHT, + HID_USAGE_SENSOR_LIGHT_ILLUM, }; /* Channel definitions */ @@ -45,7 +51,8 @@ static const struct iio_chan_spec als_channels[] = { .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), + BIT(IIO_CHAN_INFO_HYSTERESIS) | + BIT(IIO_CHAN_INFO_HYSTERESIS_RELATIVE), .scan_index = CHANNEL_SCAN_INDEX_INTENSITY, }, { @@ -54,9 +61,11 @@ static const struct iio_chan_spec als_channels[] = { .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), + BIT(IIO_CHAN_INFO_HYSTERESIS) | + BIT(IIO_CHAN_INFO_HYSTERESIS_RELATIVE), .scan_index = CHANNEL_SCAN_INDEX_ILLUM, - } + }, + IIO_CHAN_SOFT_TIMESTAMP(CHANNEL_SCAN_INDEX_TIMESTAMP) }; /* Adjust channel real bits based on report descriptor */ @@ -131,6 +140,10 @@ static int als_read_raw(struct iio_dev *indio_dev, ret_type = hid_sensor_read_raw_hyst_value( &als_state->common_attributes, val, val2); break; + case IIO_CHAN_INFO_HYSTERESIS_RELATIVE: + ret_type = hid_sensor_read_raw_hyst_rel_value( + &als_state->common_attributes, val, val2); + break; default: ret_type = -EINVAL; break; @@ -158,6 +171,10 @@ static int als_write_raw(struct iio_dev *indio_dev, ret = hid_sensor_write_raw_hyst_value( &als_state->common_attributes, val, val2); break; + case IIO_CHAN_INFO_HYSTERESIS_RELATIVE: + ret = hid_sensor_write_raw_hyst_rel_value( + &als_state->common_attributes, val, val2); + break; default: ret = -EINVAL; } @@ -170,14 +187,6 @@ static const struct iio_info als_info = { .write_raw = &als_write_raw, }; -/* Function to push data to buffer */ -static void hid_sensor_push_data(struct iio_dev *indio_dev, const void *data, - int len) -{ - dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n"); - iio_push_to_buffers(indio_dev, data); -} - /* Callback handler to send event after all samples are received and captured */ static int als_proc_event(struct hid_sensor_hub_device *hsdev, unsigned usage_id, @@ -187,10 +196,14 @@ static int als_proc_event(struct hid_sensor_hub_device *hsdev, struct als_state *als_state = iio_priv(indio_dev); dev_dbg(&indio_dev->dev, "als_proc_event\n"); - if (atomic_read(&als_state->common_attributes.data_ready)) - hid_sensor_push_data(indio_dev, - &als_state->illum, - sizeof(als_state->illum)); + if (atomic_read(&als_state->common_attributes.data_ready)) { + if (!als_state->timestamp) + als_state->timestamp = iio_get_time_ns(indio_dev); + + iio_push_to_buffers_with_timestamp(indio_dev, &als_state->scan, + als_state->timestamp); + als_state->timestamp = 0; + } return 0; } @@ -208,10 +221,14 @@ static int als_capture_sample(struct hid_sensor_hub_device *hsdev, switch (usage_id) { case HID_USAGE_SENSOR_LIGHT_ILLUM: - als_state->illum[CHANNEL_SCAN_INDEX_INTENSITY] = sample_data; - als_state->illum[CHANNEL_SCAN_INDEX_ILLUM] = sample_data; + als_state->scan.illum[CHANNEL_SCAN_INDEX_INTENSITY] = sample_data; + als_state->scan.illum[CHANNEL_SCAN_INDEX_ILLUM] = sample_data; ret = 0; break; + case HID_USAGE_SENSOR_TIME_TIMESTAMP: + als_state->timestamp = hid_sensor_convert_timestamp(&als_state->common_attributes, + *(s64 *)raw_data); + break; default: break; } @@ -247,17 +264,6 @@ static int als_parse_report(struct platform_device *pdev, &st->als_illum, &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, - HID_FEATURE_REPORT, usage_id, - HID_USAGE_SENSOR_DATA_MOD_CHANGE_SENSITIVITY_ABS | - HID_USAGE_SENSOR_DATA_LIGHT, - &st->common_attributes.sensitivity); - dev_dbg(&pdev->dev, "Sensitivity index:report %d:%d\n", - st->common_attributes.sensitivity.index, - st->common_attributes.sensitivity.report_id); - } return ret; } @@ -280,14 +286,16 @@ static int hid_als_probe(struct platform_device *pdev) als_state->common_attributes.pdev = pdev; ret = hid_sensor_parse_common_attributes(hsdev, HID_USAGE_SENSOR_ALS, - &als_state->common_attributes); + &als_state->common_attributes, + als_sensitivity_addresses, + ARRAY_SIZE(als_sensitivity_addresses)); if (ret) { dev_err(&pdev->dev, "failed to setup common attributes\n"); return ret; } - indio_dev->channels = kmemdup(als_channels, - sizeof(als_channels), GFP_KERNEL); + indio_dev->channels = devm_kmemdup(&pdev->dev, als_channels, + sizeof(als_channels), GFP_KERNEL); if (!indio_dev->channels) { dev_err(&pdev->dev, "failed to duplicate channels\n"); return -ENOMEM; @@ -298,28 +306,22 @@ static int hid_als_probe(struct platform_device *pdev) HID_USAGE_SENSOR_ALS, als_state); if (ret) { dev_err(&pdev->dev, "failed to setup attributes\n"); - goto error_free_dev_mem; + return ret; } indio_dev->num_channels = ARRAY_SIZE(als_channels); - indio_dev->dev.parent = &pdev->dev; indio_dev->info = &als_info; indio_dev->name = name; indio_dev->modes = INDIO_DIRECT_MODE; - ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time, - NULL, NULL); - if (ret) { - dev_err(&pdev->dev, "failed to initialize trigger buffer\n"); - goto error_free_dev_mem; - } atomic_set(&als_state->common_attributes.data_ready, 0); + ret = hid_sensor_setup_trigger(indio_dev, name, &als_state->common_attributes); if (ret < 0) { dev_err(&pdev->dev, "trigger setup failed\n"); - goto error_unreg_buffer_funcs; + return ret; } ret = iio_device_register(indio_dev); @@ -343,11 +345,7 @@ static int hid_als_probe(struct platform_device *pdev) error_iio_unreg: iio_device_unregister(indio_dev); error_remove_trigger: - hid_sensor_remove_trigger(&als_state->common_attributes); -error_unreg_buffer_funcs: - iio_triggered_buffer_cleanup(indio_dev); -error_free_dev_mem: - kfree(indio_dev->channels); + hid_sensor_remove_trigger(indio_dev, &als_state->common_attributes); return ret; } @@ -360,9 +358,7 @@ static int hid_als_remove(struct platform_device *pdev) sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_ALS); iio_device_unregister(indio_dev); - hid_sensor_remove_trigger(&als_state->common_attributes); - iio_triggered_buffer_cleanup(indio_dev); - kfree(indio_dev->channels); + hid_sensor_remove_trigger(indio_dev, &als_state->common_attributes); return 0; } @@ -390,3 +386,4 @@ module_platform_driver(hid_als_platform_driver); MODULE_DESCRIPTION("HID Sensor ALS"); MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@intel.com>"); MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS(IIO_HID); |