root/drivers/iio/common/hid-sensors/hid-sensor-trigger.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. _hid_sensor_set_report_latency
  2. _hid_sensor_get_report_latency
  3. _hid_sensor_get_fifo_state
  4. hid_sensor_setup_batch_mode
  5. _hid_sensor_power_state
  6. hid_sensor_power_state
  7. hid_sensor_set_power_work
  8. hid_sensor_data_rdy_trigger_set_state
  9. hid_sensor_remove_trigger
  10. hid_sensor_setup_trigger
  11. hid_sensor_suspend
  12. hid_sensor_resume
  13. hid_sensor_runtime_resume

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * HID Sensors Driver
   4  * Copyright (c) 2012, Intel Corporation.
   5  */
   6 #include <linux/device.h>
   7 #include <linux/platform_device.h>
   8 #include <linux/module.h>
   9 #include <linux/interrupt.h>
  10 #include <linux/irq.h>
  11 #include <linux/slab.h>
  12 #include <linux/delay.h>
  13 #include <linux/hid-sensor-hub.h>
  14 #include <linux/iio/iio.h>
  15 #include <linux/iio/trigger.h>
  16 #include <linux/iio/buffer.h>
  17 #include <linux/iio/sysfs.h>
  18 #include "hid-sensor-trigger.h"
  19 
  20 static ssize_t _hid_sensor_set_report_latency(struct device *dev,
  21                                               struct device_attribute *attr,
  22                                               const char *buf, size_t len)
  23 {
  24         struct iio_dev *indio_dev = dev_to_iio_dev(dev);
  25         struct hid_sensor_common *attrb = iio_device_get_drvdata(indio_dev);
  26         int integer, fract, ret;
  27         int latency;
  28 
  29         ret = iio_str_to_fixpoint(buf, 100000, &integer, &fract);
  30         if (ret)
  31                 return ret;
  32 
  33         latency = integer * 1000 + fract / 1000;
  34         ret = hid_sensor_set_report_latency(attrb, latency);
  35         if (ret < 0)
  36                 return len;
  37 
  38         attrb->latency_ms = hid_sensor_get_report_latency(attrb);
  39 
  40         return len;
  41 }
  42 
  43 static ssize_t _hid_sensor_get_report_latency(struct device *dev,
  44                                               struct device_attribute *attr,
  45                                               char *buf)
  46 {
  47         struct iio_dev *indio_dev = dev_to_iio_dev(dev);
  48         struct hid_sensor_common *attrb = iio_device_get_drvdata(indio_dev);
  49         int latency;
  50 
  51         latency = hid_sensor_get_report_latency(attrb);
  52         if (latency < 0)
  53                 return latency;
  54 
  55         return sprintf(buf, "%d.%06u\n", latency / 1000, (latency % 1000) * 1000);
  56 }
  57 
  58 static ssize_t _hid_sensor_get_fifo_state(struct device *dev,
  59                                           struct device_attribute *attr,
  60                                           char *buf)
  61 {
  62         struct iio_dev *indio_dev = dev_to_iio_dev(dev);
  63         struct hid_sensor_common *attrb = iio_device_get_drvdata(indio_dev);
  64         int latency;
  65 
  66         latency = hid_sensor_get_report_latency(attrb);
  67         if (latency < 0)
  68                 return latency;
  69 
  70         return sprintf(buf, "%d\n", !!latency);
  71 }
  72 
  73 static IIO_DEVICE_ATTR(hwfifo_timeout, 0644,
  74                        _hid_sensor_get_report_latency,
  75                        _hid_sensor_set_report_latency, 0);
  76 static IIO_DEVICE_ATTR(hwfifo_enabled, 0444,
  77                        _hid_sensor_get_fifo_state, NULL, 0);
  78 
  79 static const struct attribute *hid_sensor_fifo_attributes[] = {
  80         &iio_dev_attr_hwfifo_timeout.dev_attr.attr,
  81         &iio_dev_attr_hwfifo_enabled.dev_attr.attr,
  82         NULL,
  83 };
  84 
  85 static void hid_sensor_setup_batch_mode(struct iio_dev *indio_dev,
  86                                         struct hid_sensor_common *st)
  87 {
  88         if (!hid_sensor_batch_mode_supported(st))
  89                 return;
  90 
  91         iio_buffer_set_attrs(indio_dev->buffer, hid_sensor_fifo_attributes);
  92 }
  93 
  94 static int _hid_sensor_power_state(struct hid_sensor_common *st, bool state)
  95 {
  96         int state_val;
  97         int report_val;
  98         s32 poll_value = 0;
  99 
 100         if (state) {
 101                 if (sensor_hub_device_open(st->hsdev))
 102                         return -EIO;
 103 
 104                 atomic_inc(&st->data_ready);
 105 
 106                 state_val = hid_sensor_get_usage_index(st->hsdev,
 107                         st->power_state.report_id,
 108                         st->power_state.index,
 109                         HID_USAGE_SENSOR_PROP_POWER_STATE_D0_FULL_POWER_ENUM);
 110                 report_val = hid_sensor_get_usage_index(st->hsdev,
 111                         st->report_state.report_id,
 112                         st->report_state.index,
 113                         HID_USAGE_SENSOR_PROP_REPORTING_STATE_ALL_EVENTS_ENUM);
 114 
 115                 poll_value = hid_sensor_read_poll_value(st);
 116         } else {
 117                 int val;
 118 
 119                 val = atomic_dec_if_positive(&st->data_ready);
 120                 if (val < 0)
 121                         return 0;
 122 
 123                 sensor_hub_device_close(st->hsdev);
 124                 state_val = hid_sensor_get_usage_index(st->hsdev,
 125                         st->power_state.report_id,
 126                         st->power_state.index,
 127                         HID_USAGE_SENSOR_PROP_POWER_STATE_D4_POWER_OFF_ENUM);
 128                 report_val = hid_sensor_get_usage_index(st->hsdev,
 129                         st->report_state.report_id,
 130                         st->report_state.index,
 131                         HID_USAGE_SENSOR_PROP_REPORTING_STATE_NO_EVENTS_ENUM);
 132         }
 133 
 134         if (state_val >= 0) {
 135                 state_val += st->power_state.logical_minimum;
 136                 sensor_hub_set_feature(st->hsdev, st->power_state.report_id,
 137                                        st->power_state.index, sizeof(state_val),
 138                                        &state_val);
 139         }
 140 
 141         if (report_val >= 0) {
 142                 report_val += st->report_state.logical_minimum;
 143                 sensor_hub_set_feature(st->hsdev, st->report_state.report_id,
 144                                        st->report_state.index,
 145                                        sizeof(report_val),
 146                                        &report_val);
 147         }
 148 
 149         pr_debug("HID_SENSOR %s set power_state %d report_state %d\n",
 150                  st->pdev->name, state_val, report_val);
 151 
 152         sensor_hub_get_feature(st->hsdev, st->power_state.report_id,
 153                                st->power_state.index,
 154                                sizeof(state_val), &state_val);
 155         if (state && poll_value)
 156                 msleep_interruptible(poll_value * 2);
 157 
 158         return 0;
 159 }
 160 EXPORT_SYMBOL(hid_sensor_power_state);
 161 
 162 int hid_sensor_power_state(struct hid_sensor_common *st, bool state)
 163 {
 164 
 165 #ifdef CONFIG_PM
 166         int ret;
 167 
 168         if (atomic_add_unless(&st->runtime_pm_enable, 1, 1))
 169                 pm_runtime_enable(&st->pdev->dev);
 170 
 171         if (state) {
 172                 atomic_inc(&st->user_requested_state);
 173                 ret = pm_runtime_get_sync(&st->pdev->dev);
 174         } else {
 175                 atomic_dec(&st->user_requested_state);
 176                 pm_runtime_mark_last_busy(&st->pdev->dev);
 177                 pm_runtime_use_autosuspend(&st->pdev->dev);
 178                 ret = pm_runtime_put_autosuspend(&st->pdev->dev);
 179         }
 180         if (ret < 0) {
 181                 if (state)
 182                         pm_runtime_put_noidle(&st->pdev->dev);
 183                 return ret;
 184         }
 185 
 186         return 0;
 187 #else
 188         atomic_set(&st->user_requested_state, state);
 189         return _hid_sensor_power_state(st, state);
 190 #endif
 191 }
 192 
 193 static void hid_sensor_set_power_work(struct work_struct *work)
 194 {
 195         struct hid_sensor_common *attrb = container_of(work,
 196                                                        struct hid_sensor_common,
 197                                                        work);
 198 
 199         if (attrb->poll_interval >= 0)
 200                 sensor_hub_set_feature(attrb->hsdev, attrb->poll.report_id,
 201                                        attrb->poll.index,
 202                                        sizeof(attrb->poll_interval),
 203                                        &attrb->poll_interval);
 204 
 205         if (attrb->raw_hystersis >= 0)
 206                 sensor_hub_set_feature(attrb->hsdev,
 207                                        attrb->sensitivity.report_id,
 208                                        attrb->sensitivity.index,
 209                                        sizeof(attrb->raw_hystersis),
 210                                        &attrb->raw_hystersis);
 211 
 212         if (attrb->latency_ms > 0)
 213                 hid_sensor_set_report_latency(attrb, attrb->latency_ms);
 214 
 215         if (atomic_read(&attrb->user_requested_state))
 216                 _hid_sensor_power_state(attrb, true);
 217 }
 218 
 219 static int hid_sensor_data_rdy_trigger_set_state(struct iio_trigger *trig,
 220                                                 bool state)
 221 {
 222         return hid_sensor_power_state(iio_trigger_get_drvdata(trig), state);
 223 }
 224 
 225 void hid_sensor_remove_trigger(struct hid_sensor_common *attrb)
 226 {
 227         if (atomic_read(&attrb->runtime_pm_enable))
 228                 pm_runtime_disable(&attrb->pdev->dev);
 229 
 230         pm_runtime_set_suspended(&attrb->pdev->dev);
 231         pm_runtime_put_noidle(&attrb->pdev->dev);
 232 
 233         cancel_work_sync(&attrb->work);
 234         iio_trigger_unregister(attrb->trigger);
 235         iio_trigger_free(attrb->trigger);
 236 }
 237 EXPORT_SYMBOL(hid_sensor_remove_trigger);
 238 
 239 static const struct iio_trigger_ops hid_sensor_trigger_ops = {
 240         .set_trigger_state = &hid_sensor_data_rdy_trigger_set_state,
 241 };
 242 
 243 int hid_sensor_setup_trigger(struct iio_dev *indio_dev, const char *name,
 244                                 struct hid_sensor_common *attrb)
 245 {
 246         int ret;
 247         struct iio_trigger *trig;
 248 
 249         trig = iio_trigger_alloc("%s-dev%d", name, indio_dev->id);
 250         if (trig == NULL) {
 251                 dev_err(&indio_dev->dev, "Trigger Allocate Failed\n");
 252                 ret = -ENOMEM;
 253                 goto error_ret;
 254         }
 255 
 256         trig->dev.parent = indio_dev->dev.parent;
 257         iio_trigger_set_drvdata(trig, attrb);
 258         trig->ops = &hid_sensor_trigger_ops;
 259         ret = iio_trigger_register(trig);
 260 
 261         if (ret) {
 262                 dev_err(&indio_dev->dev, "Trigger Register Failed\n");
 263                 goto error_free_trig;
 264         }
 265         attrb->trigger = trig;
 266         indio_dev->trig = iio_trigger_get(trig);
 267 
 268         hid_sensor_setup_batch_mode(indio_dev, attrb);
 269 
 270         ret = pm_runtime_set_active(&indio_dev->dev);
 271         if (ret)
 272                 goto error_unreg_trigger;
 273 
 274         iio_device_set_drvdata(indio_dev, attrb);
 275 
 276         INIT_WORK(&attrb->work, hid_sensor_set_power_work);
 277 
 278         pm_suspend_ignore_children(&attrb->pdev->dev, true);
 279         /* Default to 3 seconds, but can be changed from sysfs */
 280         pm_runtime_set_autosuspend_delay(&attrb->pdev->dev,
 281                                          3000);
 282         return ret;
 283 error_unreg_trigger:
 284         iio_trigger_unregister(trig);
 285 error_free_trig:
 286         iio_trigger_free(trig);
 287 error_ret:
 288         return ret;
 289 }
 290 EXPORT_SYMBOL(hid_sensor_setup_trigger);
 291 
 292 static int __maybe_unused hid_sensor_suspend(struct device *dev)
 293 {
 294         struct iio_dev *indio_dev = dev_get_drvdata(dev);
 295         struct hid_sensor_common *attrb = iio_device_get_drvdata(indio_dev);
 296 
 297         return _hid_sensor_power_state(attrb, false);
 298 }
 299 
 300 static int __maybe_unused hid_sensor_resume(struct device *dev)
 301 {
 302         struct iio_dev *indio_dev = dev_get_drvdata(dev);
 303         struct hid_sensor_common *attrb = iio_device_get_drvdata(indio_dev);
 304         schedule_work(&attrb->work);
 305         return 0;
 306 }
 307 
 308 static int __maybe_unused hid_sensor_runtime_resume(struct device *dev)
 309 {
 310         struct iio_dev *indio_dev = dev_get_drvdata(dev);
 311         struct hid_sensor_common *attrb = iio_device_get_drvdata(indio_dev);
 312         return _hid_sensor_power_state(attrb, true);
 313 }
 314 
 315 const struct dev_pm_ops hid_sensor_pm_ops = {
 316         SET_SYSTEM_SLEEP_PM_OPS(hid_sensor_suspend, hid_sensor_resume)
 317         SET_RUNTIME_PM_OPS(hid_sensor_suspend,
 318                            hid_sensor_runtime_resume, NULL)
 319 };
 320 EXPORT_SYMBOL(hid_sensor_pm_ops);
 321 
 322 MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@intel.com>");
 323 MODULE_DESCRIPTION("HID Sensor trigger processing");
 324 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */