aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSrinivas Pandruvada <srinivas.pandruvada@linux.intel.com>2017-04-07 22:22:06 -0400
committerJonathan Cameron <jic23@kernel.org>2017-05-16 14:44:01 -0400
commit138bc7969c24c6cbba28e919c2376ad10a46fc60 (patch)
tree0de82ecba4edebb0bcd40fc10663b952027bdf24
parent371894f5d1a00cd6c03aab0beb9789b474ea46b0 (diff)
iio: hid-sensor-hub: Implement batch mode
HID sensor hubs using Integrated Senor Hub (ISH) has added capability to support batch mode. This allows host processor to go to sleep for extended duration, while the sensor hub is storing samples in its internal buffers. 'Commit f4f4673b7535 ("iio: add support for hardware fifo")' implements feature in IIO core to implement such feature. This feature is used in bmc150-accel-core.c to implement batch mode. This implementation allows software device buffer watermark to be used as a hint to adjust hardware FIFO. But HID sensor hubs don't allow to change internal buffer size of FIFOs. Instead an additional usage id to set "maximum report latency" is defined. This allows host to go to sleep upto this latency period without getting any report. Since there is no ABI to set this latency, a new attribute "hwfifo_timeout" is added so that user mode can specify a latency. This change checks presence of usage id to get/set maximum report latency and if present, it will expose hwfifo_timeout. Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
-rw-r--r--Documentation/ABI/testing/sysfs-bus-iio11
-rw-r--r--drivers/iio/common/hid-sensors/hid-sensor-attributes.c44
-rw-r--r--drivers/iio/common/hid-sensors/hid-sensor-trigger.c80
-rw-r--r--include/linux/hid-sensor-hub.h5
-rw-r--r--include/linux/hid-sensor-ids.h3
5 files changed, 143 insertions, 0 deletions
diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio
index 8c24d0892f61..2db2cdf42d54 100644
--- a/Documentation/ABI/testing/sysfs-bus-iio
+++ b/Documentation/ABI/testing/sysfs-bus-iio
@@ -1425,6 +1425,17 @@ Description:
1425 guarantees that the hardware fifo is flushed to the device 1425 guarantees that the hardware fifo is flushed to the device
1426 buffer. 1426 buffer.
1427 1427
1428What: /sys/bus/iio/devices/iio:device*/buffer/hwfifo_timeout
1429KernelVersion: 4.12
1430Contact: linux-iio@vger.kernel.org
1431Description:
1432 A read/write property to provide capability to delay reporting of
1433 samples till a timeout is reached. This allows host processors to
1434 sleep, while the sensor is storing samples in its internal fifo.
1435 The maximum timeout in seconds can be specified by setting
1436 hwfifo_timeout.The current delay can be read by reading
1437 hwfifo_timeout. A value of 0 means that there is no timeout.
1438
1428What: /sys/bus/iio/devices/iio:deviceX/buffer/hwfifo_watermark 1439What: /sys/bus/iio/devices/iio:deviceX/buffer/hwfifo_watermark
1429KernelVersion: 4.2 1440KernelVersion: 4.2
1430Contact: linux-iio@vger.kernel.org 1441Contact: linux-iio@vger.kernel.org
diff --git a/drivers/iio/common/hid-sensors/hid-sensor-attributes.c b/drivers/iio/common/hid-sensors/hid-sensor-attributes.c
index 0e05f6d1e761..f5d4d786e193 100644
--- a/drivers/iio/common/hid-sensors/hid-sensor-attributes.c
+++ b/drivers/iio/common/hid-sensors/hid-sensor-attributes.c
@@ -410,6 +410,48 @@ int hid_sensor_get_reporting_interval(struct hid_sensor_hub_device *hsdev,
410 410
411} 411}
412 412
413static void hid_sensor_get_report_latency_info(struct hid_sensor_hub_device *hsdev,
414 u32 usage_id,
415 struct hid_sensor_common *st)
416{
417 sensor_hub_input_get_attribute_info(hsdev, HID_FEATURE_REPORT,
418 usage_id,
419 HID_USAGE_SENSOR_PROP_REPORT_LATENCY,
420 &st->report_latency);
421
422 hid_dbg(hsdev->hdev, "Report latency attributes: %x:%x\n",
423 st->report_latency.index, st->report_latency.report_id);
424}
425
426int hid_sensor_get_report_latency(struct hid_sensor_common *st)
427{
428 int ret;
429 int value;
430
431 ret = sensor_hub_get_feature(st->hsdev, st->report_latency.report_id,
432 st->report_latency.index, sizeof(value),
433 &value);
434 if (ret < 0)
435 return ret;
436
437 return value;
438}
439EXPORT_SYMBOL(hid_sensor_get_report_latency);
440
441int hid_sensor_set_report_latency(struct hid_sensor_common *st, int latency_ms)
442{
443 return sensor_hub_set_feature(st->hsdev, st->report_latency.report_id,
444 st->report_latency.index,
445 sizeof(latency_ms), &latency_ms);
446}
447EXPORT_SYMBOL(hid_sensor_set_report_latency);
448
449bool hid_sensor_batch_mode_supported(struct hid_sensor_common *st)
450{
451 return st->report_latency.index > 0 && st->report_latency.report_id > 0;
452}
453EXPORT_SYMBOL(hid_sensor_batch_mode_supported);
454
413int hid_sensor_parse_common_attributes(struct hid_sensor_hub_device *hsdev, 455int hid_sensor_parse_common_attributes(struct hid_sensor_hub_device *hsdev,
414 u32 usage_id, 456 u32 usage_id,
415 struct hid_sensor_common *st) 457 struct hid_sensor_common *st)
@@ -451,6 +493,8 @@ int hid_sensor_parse_common_attributes(struct hid_sensor_hub_device *hsdev,
451 } else 493 } else
452 st->timestamp_ns_scale = 1000000000; 494 st->timestamp_ns_scale = 1000000000;
453 495
496 hid_sensor_get_report_latency_info(hsdev, usage_id, st);
497
454 hid_dbg(hsdev->hdev, "common attributes: %x:%x, %x:%x, %x:%x %x:%x %x:%x\n", 498 hid_dbg(hsdev->hdev, "common attributes: %x:%x, %x:%x, %x:%x %x:%x %x:%x\n",
455 st->poll.index, st->poll.report_id, 499 st->poll.index, st->poll.report_id,
456 st->report_state.index, st->report_state.report_id, 500 st->report_state.index, st->report_state.report_id,
diff --git a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
index 0b5dea050239..16ade0a0327b 100644
--- a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
+++ b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
@@ -26,9 +26,84 @@
26#include <linux/hid-sensor-hub.h> 26#include <linux/hid-sensor-hub.h>
27#include <linux/iio/iio.h> 27#include <linux/iio/iio.h>
28#include <linux/iio/trigger.h> 28#include <linux/iio/trigger.h>
29#include <linux/iio/buffer.h>
29#include <linux/iio/sysfs.h> 30#include <linux/iio/sysfs.h>
30#include "hid-sensor-trigger.h" 31#include "hid-sensor-trigger.h"
31 32
33static ssize_t _hid_sensor_set_report_latency(struct device *dev,
34 struct device_attribute *attr,
35 const char *buf, size_t len)
36{
37 struct iio_dev *indio_dev = dev_to_iio_dev(dev);
38 struct hid_sensor_common *attrb = iio_device_get_drvdata(indio_dev);
39 int integer, fract, ret;
40 int latency;
41
42 ret = iio_str_to_fixpoint(buf, 100000, &integer, &fract);
43 if (ret)
44 return ret;
45
46 latency = integer * 1000 + fract / 1000;
47 ret = hid_sensor_set_report_latency(attrb, latency);
48 if (ret < 0)
49 return len;
50
51 attrb->latency_ms = hid_sensor_get_report_latency(attrb);
52
53 return len;
54}
55
56static ssize_t _hid_sensor_get_report_latency(struct device *dev,
57 struct device_attribute *attr,
58 char *buf)
59{
60 struct iio_dev *indio_dev = dev_to_iio_dev(dev);
61 struct hid_sensor_common *attrb = iio_device_get_drvdata(indio_dev);
62 int latency;
63
64 latency = hid_sensor_get_report_latency(attrb);
65 if (latency < 0)
66 return latency;
67
68 return sprintf(buf, "%d.%06u\n", latency / 1000, (latency % 1000) * 1000);
69}
70
71static ssize_t _hid_sensor_get_fifo_state(struct device *dev,
72 struct device_attribute *attr,
73 char *buf)
74{
75 struct iio_dev *indio_dev = dev_to_iio_dev(dev);
76 struct hid_sensor_common *attrb = iio_device_get_drvdata(indio_dev);
77 int latency;
78
79 latency = hid_sensor_get_report_latency(attrb);
80 if (latency < 0)
81 return latency;
82
83 return sprintf(buf, "%d\n", !!latency);
84}
85
86static IIO_DEVICE_ATTR(hwfifo_timeout, 0644,
87 _hid_sensor_get_report_latency,
88 _hid_sensor_set_report_latency, 0);
89static IIO_DEVICE_ATTR(hwfifo_enabled, 0444,
90 _hid_sensor_get_fifo_state, NULL, 0);
91
92static const struct attribute *hid_sensor_fifo_attributes[] = {
93 &iio_dev_attr_hwfifo_timeout.dev_attr.attr,
94 &iio_dev_attr_hwfifo_enabled.dev_attr.attr,
95 NULL,
96};
97
98static void hid_sensor_setup_batch_mode(struct iio_dev *indio_dev,
99 struct hid_sensor_common *st)
100{
101 if (!hid_sensor_batch_mode_supported(st))
102 return;
103
104 iio_buffer_set_attrs(indio_dev->buffer, hid_sensor_fifo_attributes);
105}
106
32static int _hid_sensor_power_state(struct hid_sensor_common *st, bool state) 107static int _hid_sensor_power_state(struct hid_sensor_common *st, bool state)
33{ 108{
34 int state_val; 109 int state_val;
@@ -141,6 +216,9 @@ static void hid_sensor_set_power_work(struct work_struct *work)
141 sizeof(attrb->raw_hystersis), 216 sizeof(attrb->raw_hystersis),
142 &attrb->raw_hystersis); 217 &attrb->raw_hystersis);
143 218
219 if (attrb->latency_ms > 0)
220 hid_sensor_set_report_latency(attrb, attrb->latency_ms);
221
144 _hid_sensor_power_state(attrb, true); 222 _hid_sensor_power_state(attrb, true);
145} 223}
146 224
@@ -192,6 +270,8 @@ int hid_sensor_setup_trigger(struct iio_dev *indio_dev, const char *name,
192 attrb->trigger = trig; 270 attrb->trigger = trig;
193 indio_dev->trig = iio_trigger_get(trig); 271 indio_dev->trig = iio_trigger_get(trig);
194 272
273 hid_sensor_setup_batch_mode(indio_dev, attrb);
274
195 ret = pm_runtime_set_active(&indio_dev->dev); 275 ret = pm_runtime_set_active(&indio_dev->dev);
196 if (ret) 276 if (ret)
197 goto error_unreg_trigger; 277 goto error_unreg_trigger;
diff --git a/include/linux/hid-sensor-hub.h b/include/linux/hid-sensor-hub.h
index f32d7c392c1e..fc7aae64dcde 100644
--- a/include/linux/hid-sensor-hub.h
+++ b/include/linux/hid-sensor-hub.h
@@ -233,12 +233,14 @@ struct hid_sensor_common {
233 atomic_t user_requested_state; 233 atomic_t user_requested_state;
234 int poll_interval; 234 int poll_interval;
235 int raw_hystersis; 235 int raw_hystersis;
236 int latency_ms;
236 struct iio_trigger *trigger; 237 struct iio_trigger *trigger;
237 int timestamp_ns_scale; 238 int timestamp_ns_scale;
238 struct hid_sensor_hub_attribute_info poll; 239 struct hid_sensor_hub_attribute_info poll;
239 struct hid_sensor_hub_attribute_info report_state; 240 struct hid_sensor_hub_attribute_info report_state;
240 struct hid_sensor_hub_attribute_info power_state; 241 struct hid_sensor_hub_attribute_info power_state;
241 struct hid_sensor_hub_attribute_info sensitivity; 242 struct hid_sensor_hub_attribute_info sensitivity;
243 struct hid_sensor_hub_attribute_info report_latency;
242 struct work_struct work; 244 struct work_struct work;
243}; 245};
244 246
@@ -276,5 +278,8 @@ s32 hid_sensor_read_poll_value(struct hid_sensor_common *st);
276 278
277int64_t hid_sensor_convert_timestamp(struct hid_sensor_common *st, 279int64_t hid_sensor_convert_timestamp(struct hid_sensor_common *st,
278 int64_t raw_value); 280 int64_t raw_value);
281bool hid_sensor_batch_mode_supported(struct hid_sensor_common *st);
282int hid_sensor_set_report_latency(struct hid_sensor_common *st, int latency);
283int hid_sensor_get_report_latency(struct hid_sensor_common *st);
279 284
280#endif 285#endif
diff --git a/include/linux/hid-sensor-ids.h b/include/linux/hid-sensor-ids.h
index 5af62c7e49f3..76033e0420a7 100644
--- a/include/linux/hid-sensor-ids.h
+++ b/include/linux/hid-sensor-ids.h
@@ -152,6 +152,9 @@
152#define HID_USAGE_SENSOR_PROP_REPORT_STATE 0x200316 152#define HID_USAGE_SENSOR_PROP_REPORT_STATE 0x200316
153#define HID_USAGE_SENSOR_PROY_POWER_STATE 0x200319 153#define HID_USAGE_SENSOR_PROY_POWER_STATE 0x200319
154 154
155/* Batch mode selectors */
156#define HID_USAGE_SENSOR_PROP_REPORT_LATENCY 0x20031B
157
155/* Per data field properties */ 158/* Per data field properties */
156#define HID_USAGE_SENSOR_DATA_MOD_NONE 0x00 159#define HID_USAGE_SENSOR_DATA_MOD_NONE 0x00
157#define HID_USAGE_SENSOR_DATA_MOD_CHANGE_SENSITIVITY_ABS 0x1000 160#define HID_USAGE_SENSOR_DATA_MOD_CHANGE_SENSITIVITY_ABS 0x1000