From de01d65795647e66b29bf1400c2b5c39998a47d8 Mon Sep 17 00:00:00 2001 From: Stefan Brüns Date: Mon, 1 May 2017 13:19:41 +0200 Subject: iio: Documentation: sysfs-bus-iio-meas-spec: Remove (partially) duplicate line MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Stefan Brüns Signed-off-by: Jonathan Cameron --- Documentation/ABI/testing/sysfs-bus-iio-meas-spec | 1 - 1 file changed, 1 deletion(-) (limited to 'Documentation/ABI') diff --git a/Documentation/ABI/testing/sysfs-bus-iio-meas-spec b/Documentation/ABI/testing/sysfs-bus-iio-meas-spec index 1a6265e92e2f..6d47e548eee5 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio-meas-spec +++ b/Documentation/ABI/testing/sysfs-bus-iio-meas-spec @@ -5,4 +5,3 @@ Description: Reading returns either '1' or '0'. '1' means that the battery level supplied to sensor is below 2.25V. This ABI is available for tsys02d, htu21, ms8607 - This ABI is available for htu21, ms8607 -- cgit v1.2.3 From 6fb34812c2a2a4cdcdad4452b9634892812fa97b Mon Sep 17 00:00:00 2001 From: Fabrice Gasnier Date: Tue, 2 May 2017 14:33:45 +0200 Subject: iio: stm32 trigger: Add support for TRGO2 triggers Add support for TRGO2 trigger that can be found on STM32F7. Add additional master modes supported by TRGO2. Register additional "tim[1/8]_trgo2" triggers for timer1 & timer8. Detect TRGO2 timer capability (master mode selection 2). Signed-off-by: Fabrice Gasnier Acked-by: Benjamin Gaignard Signed-off-by: Jonathan Cameron --- .../ABI/testing/sysfs-bus-iio-timer-stm32 | 48 +++++++++ drivers/iio/trigger/stm32-timer-trigger.c | 113 ++++++++++++++++++--- include/linux/iio/timer/stm32-timer-trigger.h | 2 + include/linux/mfd/stm32-timers.h | 2 + 4 files changed, 151 insertions(+), 14 deletions(-) (limited to 'Documentation/ABI') diff --git a/Documentation/ABI/testing/sysfs-bus-iio-timer-stm32 b/Documentation/ABI/testing/sysfs-bus-iio-timer-stm32 index 230020e06677..deb015935683 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio-timer-stm32 +++ b/Documentation/ABI/testing/sysfs-bus-iio-timer-stm32 @@ -16,6 +16,54 @@ Description: - "OC2REF" : OC2REF signal is used as trigger output. - "OC3REF" : OC3REF signal is used as trigger output. - "OC4REF" : OC4REF signal is used as trigger output. + Additional modes (on TRGO2 only): + - "OC5REF" : OC5REF signal is used as trigger output. + - "OC6REF" : OC6REF signal is used as trigger output. + - "compare_pulse_OC4REF": + OC4REF rising or falling edges generate pulses. + - "compare_pulse_OC6REF": + OC6REF rising or falling edges generate pulses. + - "compare_pulse_OC4REF_r_or_OC6REF_r": + OC4REF or OC6REF rising edges generate pulses. + - "compare_pulse_OC4REF_r_or_OC6REF_f": + OC4REF rising or OC6REF falling edges generate pulses. + - "compare_pulse_OC5REF_r_or_OC6REF_r": + OC5REF or OC6REF rising edges generate pulses. + - "compare_pulse_OC5REF_r_or_OC6REF_f": + OC5REF rising or OC6REF falling edges generate pulses. + + +-----------+ +-------------+ +---------+ + | Prescaler +-> | Counter | +-> | Master | TRGO(2) + +-----------+ +--+--------+-+ |-> | Control +--> + | | || +---------+ + +--v--------+-+ OCxREF || +---------+ + | Chx compare +----------> | Output | ChX + +-----------+-+ | | Control +--> + . | | +---------+ + . | | . + +-----------v-+ OC6REF | . + | Ch6 compare +---------+> + +-------------+ + + Example with: "compare_pulse_OC4REF_r_or_OC6REF_r": + + X + X X + X . . X + X . . X + X . . X + count X . . . . X + . . . . + . . . . + +---------------+ + OC4REF | . . | + +-+ . . +-+ + . +---+ . + OC6REF . | | . + +-------+ +-------+ + +-+ +-+ + TRGO2 | | | | + +-+ +---+ +---------+ What: /sys/bus/iio/devices/triggerX/master_mode KernelVersion: 4.11 diff --git a/drivers/iio/trigger/stm32-timer-trigger.c b/drivers/iio/trigger/stm32-timer-trigger.c index 25248d644e7c..0797f2fe584f 100644 --- a/drivers/iio/trigger/stm32-timer-trigger.c +++ b/drivers/iio/trigger/stm32-timer-trigger.c @@ -14,19 +14,19 @@ #include #include -#define MAX_TRIGGERS 6 +#define MAX_TRIGGERS 7 #define MAX_VALIDS 5 /* List the triggers created by each timer */ static const void *triggers_table[][MAX_TRIGGERS] = { - { TIM1_TRGO, TIM1_CH1, TIM1_CH2, TIM1_CH3, TIM1_CH4,}, + { TIM1_TRGO, TIM1_TRGO2, TIM1_CH1, TIM1_CH2, TIM1_CH3, TIM1_CH4,}, { TIM2_TRGO, TIM2_CH1, TIM2_CH2, TIM2_CH3, TIM2_CH4,}, { TIM3_TRGO, TIM3_CH1, TIM3_CH2, TIM3_CH3, TIM3_CH4,}, { TIM4_TRGO, TIM4_CH1, TIM4_CH2, TIM4_CH3, TIM4_CH4,}, { TIM5_TRGO, TIM5_CH1, TIM5_CH2, TIM5_CH3, TIM5_CH4,}, { TIM6_TRGO,}, { TIM7_TRGO,}, - { TIM8_TRGO, TIM8_CH1, TIM8_CH2, TIM8_CH3, TIM8_CH4,}, + { TIM8_TRGO, TIM8_TRGO2, TIM8_CH1, TIM8_CH2, TIM8_CH3, TIM8_CH4,}, { TIM9_TRGO, TIM9_CH1, TIM9_CH2,}, { }, /* timer 10 */ { }, /* timer 11 */ @@ -56,9 +56,16 @@ struct stm32_timer_trigger { u32 max_arr; const void *triggers; const void *valids; + bool has_trgo2; }; +static bool stm32_timer_is_trgo2_name(const char *name) +{ + return !!strstr(name, "trgo2"); +} + static int stm32_timer_start(struct stm32_timer_trigger *priv, + struct iio_trigger *trig, unsigned int frequency) { unsigned long long prd, div; @@ -102,7 +109,12 @@ static int stm32_timer_start(struct stm32_timer_trigger *priv, regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_ARPE, TIM_CR1_ARPE); /* Force master mode to update mode */ - regmap_update_bits(priv->regmap, TIM_CR2, TIM_CR2_MMS, 0x20); + if (stm32_timer_is_trgo2_name(trig->name)) + regmap_update_bits(priv->regmap, TIM_CR2, TIM_CR2_MMS2, + 0x2 << TIM_CR2_MMS2_SHIFT); + else + regmap_update_bits(priv->regmap, TIM_CR2, TIM_CR2_MMS, + 0x2 << TIM_CR2_MMS_SHIFT); /* Make sure that registers are updated */ regmap_update_bits(priv->regmap, TIM_EGR, TIM_EGR_UG, TIM_EGR_UG); @@ -150,7 +162,7 @@ static ssize_t stm32_tt_store_frequency(struct device *dev, if (freq == 0) { stm32_timer_stop(priv); } else { - ret = stm32_timer_start(priv, freq); + ret = stm32_timer_start(priv, trig, freq); if (ret) return ret; } @@ -183,6 +195,9 @@ static IIO_DEV_ATTR_SAMP_FREQ(0660, stm32_tt_read_frequency, stm32_tt_store_frequency); +#define MASTER_MODE_MAX 7 +#define MASTER_MODE2_MAX 15 + static char *master_mode_table[] = { "reset", "enable", @@ -191,7 +206,16 @@ static char *master_mode_table[] = { "OC1REF", "OC2REF", "OC3REF", - "OC4REF" + "OC4REF", + /* Master mode selection 2 only */ + "OC5REF", + "OC6REF", + "compare_pulse_OC4REF", + "compare_pulse_OC6REF", + "compare_pulse_OC4REF_r_or_OC6REF_r", + "compare_pulse_OC4REF_r_or_OC6REF_f", + "compare_pulse_OC5REF_r_or_OC6REF_r", + "compare_pulse_OC5REF_r_or_OC6REF_f", }; static ssize_t stm32_tt_show_master_mode(struct device *dev, @@ -199,10 +223,15 @@ static ssize_t stm32_tt_show_master_mode(struct device *dev, char *buf) { struct stm32_timer_trigger *priv = dev_get_drvdata(dev); + struct iio_trigger *trig = to_iio_trigger(dev); u32 cr2; regmap_read(priv->regmap, TIM_CR2, &cr2); - cr2 = (cr2 & TIM_CR2_MMS) >> TIM_CR2_MMS_SHIFT; + + if (stm32_timer_is_trgo2_name(trig->name)) + cr2 = (cr2 & TIM_CR2_MMS2) >> TIM_CR2_MMS2_SHIFT; + else + cr2 = (cr2 & TIM_CR2_MMS) >> TIM_CR2_MMS_SHIFT; return snprintf(buf, PAGE_SIZE, "%s\n", master_mode_table[cr2]); } @@ -212,13 +241,25 @@ static ssize_t stm32_tt_store_master_mode(struct device *dev, const char *buf, size_t len) { struct stm32_timer_trigger *priv = dev_get_drvdata(dev); + struct iio_trigger *trig = to_iio_trigger(dev); + u32 mask, shift, master_mode_max; int i; - for (i = 0; i < ARRAY_SIZE(master_mode_table); i++) { + if (stm32_timer_is_trgo2_name(trig->name)) { + mask = TIM_CR2_MMS2; + shift = TIM_CR2_MMS2_SHIFT; + master_mode_max = MASTER_MODE2_MAX; + } else { + mask = TIM_CR2_MMS; + shift = TIM_CR2_MMS_SHIFT; + master_mode_max = MASTER_MODE_MAX; + } + + for (i = 0; i <= master_mode_max; i++) { if (!strncmp(master_mode_table[i], buf, strlen(master_mode_table[i]))) { - regmap_update_bits(priv->regmap, TIM_CR2, - TIM_CR2_MMS, i << TIM_CR2_MMS_SHIFT); + regmap_update_bits(priv->regmap, TIM_CR2, mask, + i << shift); /* Make sure that registers are updated */ regmap_update_bits(priv->regmap, TIM_EGR, TIM_EGR_UG, TIM_EGR_UG); @@ -229,8 +270,31 @@ static ssize_t stm32_tt_store_master_mode(struct device *dev, return -EINVAL; } -static IIO_CONST_ATTR(master_mode_available, - "reset enable update compare_pulse OC1REF OC2REF OC3REF OC4REF"); +static ssize_t stm32_tt_show_master_mode_avail(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_trigger *trig = to_iio_trigger(dev); + unsigned int i, master_mode_max; + size_t len = 0; + + if (stm32_timer_is_trgo2_name(trig->name)) + master_mode_max = MASTER_MODE2_MAX; + else + master_mode_max = MASTER_MODE_MAX; + + for (i = 0; i <= master_mode_max; i++) + len += scnprintf(buf + len, PAGE_SIZE - len, + "%s ", master_mode_table[i]); + + /* replace trailing space by newline */ + buf[len - 1] = '\n'; + + return len; +} + +static IIO_DEVICE_ATTR(master_mode_available, 0444, + stm32_tt_show_master_mode_avail, NULL, 0); static IIO_DEVICE_ATTR(master_mode, 0660, stm32_tt_show_master_mode, @@ -240,7 +304,7 @@ static IIO_DEVICE_ATTR(master_mode, 0660, static struct attribute *stm32_trigger_attrs[] = { &iio_dev_attr_sampling_frequency.dev_attr.attr, &iio_dev_attr_master_mode.dev_attr.attr, - &iio_const_attr_master_mode_available.dev_attr.attr, + &iio_dev_attr_master_mode_available.dev_attr.attr, NULL, }; @@ -264,6 +328,12 @@ static int stm32_setup_iio_triggers(struct stm32_timer_trigger *priv) while (cur && *cur) { struct iio_trigger *trig; + bool cur_is_trgo2 = stm32_timer_is_trgo2_name(*cur); + + if (cur_is_trgo2 && !priv->has_trgo2) { + cur++; + continue; + } trig = devm_iio_trigger_alloc(priv->dev, "%s", *cur); if (!trig) @@ -277,7 +347,7 @@ static int stm32_setup_iio_triggers(struct stm32_timer_trigger *priv) * should only be available on trgo trigger which * is always the first in the list. */ - if (cur == priv->triggers) + if (cur == priv->triggers || cur_is_trgo2) trig->dev.groups = stm32_trigger_attr_groups; iio_trigger_set_drvdata(trig, priv); @@ -584,6 +654,20 @@ bool is_stm32_timer_trigger(struct iio_trigger *trig) } EXPORT_SYMBOL(is_stm32_timer_trigger); +static void stm32_timer_detect_trgo2(struct stm32_timer_trigger *priv) +{ + u32 val; + + /* + * Master mode selection 2 bits can only be written and read back when + * timer supports it. + */ + regmap_update_bits(priv->regmap, TIM_CR2, TIM_CR2_MMS2, TIM_CR2_MMS2); + regmap_read(priv->regmap, TIM_CR2, &val); + regmap_update_bits(priv->regmap, TIM_CR2, TIM_CR2_MMS2, 0); + priv->has_trgo2 = !!val; +} + static int stm32_timer_trigger_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -614,6 +698,7 @@ static int stm32_timer_trigger_probe(struct platform_device *pdev) priv->max_arr = ddata->max_arr; priv->triggers = triggers_table[index]; priv->valids = valids_table[index]; + stm32_timer_detect_trgo2(priv); ret = stm32_setup_iio_triggers(priv); if (ret) diff --git a/include/linux/iio/timer/stm32-timer-trigger.h b/include/linux/iio/timer/stm32-timer-trigger.h index 55535aef2e6c..fa7d786ed99e 100644 --- a/include/linux/iio/timer/stm32-timer-trigger.h +++ b/include/linux/iio/timer/stm32-timer-trigger.h @@ -10,6 +10,7 @@ #define _STM32_TIMER_TRIGGER_H_ #define TIM1_TRGO "tim1_trgo" +#define TIM1_TRGO2 "tim1_trgo2" #define TIM1_CH1 "tim1_ch1" #define TIM1_CH2 "tim1_ch2" #define TIM1_CH3 "tim1_ch3" @@ -44,6 +45,7 @@ #define TIM7_TRGO "tim7_trgo" #define TIM8_TRGO "tim8_trgo" +#define TIM8_TRGO2 "tim8_trgo2" #define TIM8_CH1 "tim8_ch1" #define TIM8_CH2 "tim8_ch2" #define TIM8_CH3 "tim8_ch3" diff --git a/include/linux/mfd/stm32-timers.h b/include/linux/mfd/stm32-timers.h index 4a0abbc10ef6..ce7346e7f77a 100644 --- a/include/linux/mfd/stm32-timers.h +++ b/include/linux/mfd/stm32-timers.h @@ -34,6 +34,7 @@ #define TIM_CR1_DIR BIT(4) /* Counter Direction */ #define TIM_CR1_ARPE BIT(7) /* Auto-reload Preload Ena */ #define TIM_CR2_MMS (BIT(4) | BIT(5) | BIT(6)) /* Master mode selection */ +#define TIM_CR2_MMS2 GENMASK(23, 20) /* Master mode selection 2 */ #define TIM_SMCR_SMS (BIT(0) | BIT(1) | BIT(2)) /* Slave mode selection */ #define TIM_SMCR_TS (BIT(4) | BIT(5) | BIT(6)) /* Trigger selection */ #define TIM_DIER_UIE BIT(0) /* Update interrupt */ @@ -60,6 +61,7 @@ #define MAX_TIM_PSC 0xFFFF #define TIM_CR2_MMS_SHIFT 4 +#define TIM_CR2_MMS2_SHIFT 20 #define TIM_SMCR_TS_SHIFT 4 #define TIM_BDTR_BKF_MASK 0xF #define TIM_BDTR_BKF_SHIFT 16 -- cgit v1.2.3 From 138bc7969c24c6cbba28e919c2376ad10a46fc60 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Fri, 7 Apr 2017 19:22:06 -0700 Subject: 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 Signed-off-by: Jonathan Cameron --- Documentation/ABI/testing/sysfs-bus-iio | 11 +++ .../iio/common/hid-sensors/hid-sensor-attributes.c | 44 ++++++++++++ .../iio/common/hid-sensors/hid-sensor-trigger.c | 80 ++++++++++++++++++++++ include/linux/hid-sensor-hub.h | 5 ++ include/linux/hid-sensor-ids.h | 3 + 5 files changed, 143 insertions(+) (limited to 'Documentation/ABI') 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: guarantees that the hardware fifo is flushed to the device buffer. +What: /sys/bus/iio/devices/iio:device*/buffer/hwfifo_timeout +KernelVersion: 4.12 +Contact: linux-iio@vger.kernel.org +Description: + A read/write property to provide capability to delay reporting of + samples till a timeout is reached. This allows host processors to + sleep, while the sensor is storing samples in its internal fifo. + The maximum timeout in seconds can be specified by setting + hwfifo_timeout.The current delay can be read by reading + hwfifo_timeout. A value of 0 means that there is no timeout. + What: /sys/bus/iio/devices/iio:deviceX/buffer/hwfifo_watermark KernelVersion: 4.2 Contact: 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, } +static void hid_sensor_get_report_latency_info(struct hid_sensor_hub_device *hsdev, + u32 usage_id, + struct hid_sensor_common *st) +{ + sensor_hub_input_get_attribute_info(hsdev, HID_FEATURE_REPORT, + usage_id, + HID_USAGE_SENSOR_PROP_REPORT_LATENCY, + &st->report_latency); + + hid_dbg(hsdev->hdev, "Report latency attributes: %x:%x\n", + st->report_latency.index, st->report_latency.report_id); +} + +int hid_sensor_get_report_latency(struct hid_sensor_common *st) +{ + int ret; + int value; + + ret = sensor_hub_get_feature(st->hsdev, st->report_latency.report_id, + st->report_latency.index, sizeof(value), + &value); + if (ret < 0) + return ret; + + return value; +} +EXPORT_SYMBOL(hid_sensor_get_report_latency); + +int hid_sensor_set_report_latency(struct hid_sensor_common *st, int latency_ms) +{ + return sensor_hub_set_feature(st->hsdev, st->report_latency.report_id, + st->report_latency.index, + sizeof(latency_ms), &latency_ms); +} +EXPORT_SYMBOL(hid_sensor_set_report_latency); + +bool hid_sensor_batch_mode_supported(struct hid_sensor_common *st) +{ + return st->report_latency.index > 0 && st->report_latency.report_id > 0; +} +EXPORT_SYMBOL(hid_sensor_batch_mode_supported); + int hid_sensor_parse_common_attributes(struct hid_sensor_hub_device *hsdev, u32 usage_id, struct hid_sensor_common *st) @@ -451,6 +493,8 @@ int hid_sensor_parse_common_attributes(struct hid_sensor_hub_device *hsdev, } else st->timestamp_ns_scale = 1000000000; + hid_sensor_get_report_latency_info(hsdev, usage_id, st); + hid_dbg(hsdev->hdev, "common attributes: %x:%x, %x:%x, %x:%x %x:%x %x:%x\n", st->poll.index, st->poll.report_id, 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 @@ #include #include #include +#include #include #include "hid-sensor-trigger.h" +static ssize_t _hid_sensor_set_report_latency(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct hid_sensor_common *attrb = iio_device_get_drvdata(indio_dev); + int integer, fract, ret; + int latency; + + ret = iio_str_to_fixpoint(buf, 100000, &integer, &fract); + if (ret) + return ret; + + latency = integer * 1000 + fract / 1000; + ret = hid_sensor_set_report_latency(attrb, latency); + if (ret < 0) + return len; + + attrb->latency_ms = hid_sensor_get_report_latency(attrb); + + return len; +} + +static ssize_t _hid_sensor_get_report_latency(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct hid_sensor_common *attrb = iio_device_get_drvdata(indio_dev); + int latency; + + latency = hid_sensor_get_report_latency(attrb); + if (latency < 0) + return latency; + + return sprintf(buf, "%d.%06u\n", latency / 1000, (latency % 1000) * 1000); +} + +static ssize_t _hid_sensor_get_fifo_state(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct hid_sensor_common *attrb = iio_device_get_drvdata(indio_dev); + int latency; + + latency = hid_sensor_get_report_latency(attrb); + if (latency < 0) + return latency; + + return sprintf(buf, "%d\n", !!latency); +} + +static IIO_DEVICE_ATTR(hwfifo_timeout, 0644, + _hid_sensor_get_report_latency, + _hid_sensor_set_report_latency, 0); +static IIO_DEVICE_ATTR(hwfifo_enabled, 0444, + _hid_sensor_get_fifo_state, NULL, 0); + +static const struct attribute *hid_sensor_fifo_attributes[] = { + &iio_dev_attr_hwfifo_timeout.dev_attr.attr, + &iio_dev_attr_hwfifo_enabled.dev_attr.attr, + NULL, +}; + +static void hid_sensor_setup_batch_mode(struct iio_dev *indio_dev, + struct hid_sensor_common *st) +{ + if (!hid_sensor_batch_mode_supported(st)) + return; + + iio_buffer_set_attrs(indio_dev->buffer, hid_sensor_fifo_attributes); +} + static int _hid_sensor_power_state(struct hid_sensor_common *st, bool state) { int state_val; @@ -141,6 +216,9 @@ static void hid_sensor_set_power_work(struct work_struct *work) sizeof(attrb->raw_hystersis), &attrb->raw_hystersis); + if (attrb->latency_ms > 0) + hid_sensor_set_report_latency(attrb, attrb->latency_ms); + _hid_sensor_power_state(attrb, true); } @@ -192,6 +270,8 @@ int hid_sensor_setup_trigger(struct iio_dev *indio_dev, const char *name, attrb->trigger = trig; indio_dev->trig = iio_trigger_get(trig); + hid_sensor_setup_batch_mode(indio_dev, attrb); + ret = pm_runtime_set_active(&indio_dev->dev); if (ret) 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 { atomic_t user_requested_state; int poll_interval; int raw_hystersis; + int latency_ms; struct iio_trigger *trigger; int timestamp_ns_scale; struct hid_sensor_hub_attribute_info poll; struct hid_sensor_hub_attribute_info report_state; struct hid_sensor_hub_attribute_info power_state; struct hid_sensor_hub_attribute_info sensitivity; + struct hid_sensor_hub_attribute_info report_latency; struct work_struct work; }; @@ -276,5 +278,8 @@ s32 hid_sensor_read_poll_value(struct hid_sensor_common *st); int64_t hid_sensor_convert_timestamp(struct hid_sensor_common *st, int64_t raw_value); +bool hid_sensor_batch_mode_supported(struct hid_sensor_common *st); +int hid_sensor_set_report_latency(struct hid_sensor_common *st, int latency); +int hid_sensor_get_report_latency(struct hid_sensor_common *st); #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 @@ #define HID_USAGE_SENSOR_PROP_REPORT_STATE 0x200316 #define HID_USAGE_SENSOR_PROY_POWER_STATE 0x200319 +/* Batch mode selectors */ +#define HID_USAGE_SENSOR_PROP_REPORT_LATENCY 0x20031B + /* Per data field properties */ #define HID_USAGE_SENSOR_DATA_MOD_NONE 0x00 #define HID_USAGE_SENSOR_DATA_MOD_CHANGE_SENSITIVITY_ABS 0x1000 -- cgit v1.2.3