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