aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorsrinivas pandruvada <srinivas.pandruvada@intel.com>2012-09-05 08:56:00 -0400
committerJonathan Cameron <jic23@kernel.org>2012-09-06 14:20:11 -0400
commit73c6768b710a1621903f2bc179ae9c7789d41e9f (patch)
treee486fe76c5fa4ba4a5cd61124b52689510169385 /drivers
parent401ca24fb34aee0cedf9c4fef361e533224f15a1 (diff)
iio: hid-sensors: Common attribute and trigger
This patch contains the common code, which is used by all HID sensors. There are some common set of attributes, which every hid sensor needs it. This patch contains all such attributes processing. Also the trigger interface is common among all HID sensors. This patch contains common trigger functions utilized by all HID sensors. Signed-off-by: srinivas pandruvada <srinivas.pandruvada@intel.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/iio/Kconfig1
-rw-r--r--drivers/iio/Makefile1
-rw-r--r--drivers/iio/common/Kconfig5
-rw-r--r--drivers/iio/common/Makefile9
-rw-r--r--drivers/iio/common/hid-sensors/Kconfig26
-rw-r--r--drivers/iio/common/hid-sensors/Makefile6
-rw-r--r--drivers/iio/common/hid-sensors/hid-sensor-attributes.c250
-rw-r--r--drivers/iio/common/hid-sensors/hid-sensor-attributes.h57
-rw-r--r--drivers/iio/common/hid-sensors/hid-sensor-trigger.c102
-rw-r--r--drivers/iio/common/hid-sensors/hid-sensor-trigger.h26
10 files changed, 483 insertions, 0 deletions
diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig
index 56825e6f5725..c40261032847 100644
--- a/drivers/iio/Kconfig
+++ b/drivers/iio/Kconfig
@@ -59,5 +59,6 @@ source "drivers/iio/amplifiers/Kconfig"
59source "drivers/iio/light/Kconfig" 59source "drivers/iio/light/Kconfig"
60source "drivers/iio/frequency/Kconfig" 60source "drivers/iio/frequency/Kconfig"
61source "drivers/iio/dac/Kconfig" 61source "drivers/iio/dac/Kconfig"
62source "drivers/iio/common/Kconfig"
62 63
63endif # IIO 64endif # IIO
diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile
index 34309abb7979..cfafb0d5af9f 100644
--- a/drivers/iio/Makefile
+++ b/drivers/iio/Makefile
@@ -15,3 +15,4 @@ obj-y += amplifiers/
15obj-y += light/ 15obj-y += light/
16obj-y += frequency/ 16obj-y += frequency/
17obj-y += dac/ 17obj-y += dac/
18obj-y += common/
diff --git a/drivers/iio/common/Kconfig b/drivers/iio/common/Kconfig
new file mode 100644
index 000000000000..ed45ee54500c
--- /dev/null
+++ b/drivers/iio/common/Kconfig
@@ -0,0 +1,5 @@
1#
2# IIO common modules
3#
4
5source "drivers/iio/common/hid-sensors/Kconfig"
diff --git a/drivers/iio/common/Makefile b/drivers/iio/common/Makefile
new file mode 100644
index 000000000000..81584009b21b
--- /dev/null
+++ b/drivers/iio/common/Makefile
@@ -0,0 +1,9 @@
1#
2# Makefile for the IIO common modules.
3# Common modules contains modules, which can be shared among multiple
4# IIO modules. For example if the trigger processing is common for
5# multiple IIO modules then this can be moved to a common module
6# instead of duplicating in each module.
7#
8
9obj-y += hid-sensors/
diff --git a/drivers/iio/common/hid-sensors/Kconfig b/drivers/iio/common/hid-sensors/Kconfig
new file mode 100644
index 000000000000..8e63d81d652a
--- /dev/null
+++ b/drivers/iio/common/hid-sensors/Kconfig
@@ -0,0 +1,26 @@
1#
2# Hid Sensor common modules
3#
4menu "Hid Sensor IIO Common"
5
6config HID_SENSOR_IIO_COMMON
7 tristate "Common modules for all HID Sensor IIO drivers"
8 depends on HID_SENSOR_HUB
9 select IIO_TRIGGER if IIO_BUFFER
10 help
11 Say yes here to build support for HID sensor to use
12 HID sensor common processing for attributes and IIO triggers.
13 There are many attributes which can be shared among multiple
14 HID sensor drivers, this module contains processing for those
15 attributes.
16
17config HID_SENSOR_ENUM_BASE_QUIRKS
18 tristate "ENUM base quirks for HID Sensor IIO drivers"
19 depends on HID_SENSOR_IIO_COMMON
20 help
21 Say yes here to build support for sensor hub FW using
22 enumeration, which is using 1 as base instead of 0.
23 Since logical minimum is still set 0 instead of 1,
24 there is no easy way to differentiate.
25
26endmenu
diff --git a/drivers/iio/common/hid-sensors/Makefile b/drivers/iio/common/hid-sensors/Makefile
new file mode 100644
index 000000000000..1f463e00c242
--- /dev/null
+++ b/drivers/iio/common/hid-sensors/Makefile
@@ -0,0 +1,6 @@
1#
2# Makefile for the Hid sensor common modules.
3#
4
5obj-$(CONFIG_HID_SENSOR_IIO_COMMON) += hid-sensor-iio-common.o
6hid-sensor-iio-common-y := hid-sensor-attributes.o hid-sensor-trigger.o
diff --git a/drivers/iio/common/hid-sensors/hid-sensor-attributes.c b/drivers/iio/common/hid-sensors/hid-sensor-attributes.c
new file mode 100644
index 000000000000..75374955caba
--- /dev/null
+++ b/drivers/iio/common/hid-sensors/hid-sensor-attributes.c
@@ -0,0 +1,250 @@
1/*
2 * HID Sensors Driver
3 * Copyright (c) 2012, Intel Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
17 *
18 */
19#include <linux/device.h>
20#include <linux/platform_device.h>
21#include <linux/module.h>
22#include <linux/interrupt.h>
23#include <linux/irq.h>
24#include <linux/slab.h>
25#include <linux/hid-sensor-hub.h>
26#include <linux/iio/iio.h>
27#include <linux/iio/sysfs.h>
28#include "hid-sensor-attributes.h"
29
30static int pow_10(unsigned power)
31{
32 int i;
33 int ret = 1;
34 for (i = 0; i < power; ++i)
35 ret = ret * 10;
36
37 return ret;
38}
39
40static void simple_div(int dividend, int divisor, int *whole,
41 int *micro_frac)
42{
43 int rem;
44 int exp = 0;
45
46 *micro_frac = 0;
47 if (divisor == 0) {
48 *whole = 0;
49 return;
50 }
51 *whole = dividend/divisor;
52 rem = dividend % divisor;
53 if (rem) {
54 while (rem <= divisor) {
55 rem *= 10;
56 exp++;
57 }
58 *micro_frac = (rem / divisor) * pow_10(6-exp);
59 }
60}
61
62static void split_micro_fraction(unsigned int no, int exp, int *val1, int *val2)
63{
64 *val1 = no/pow_10(exp);
65 *val2 = no%pow_10(exp) * pow_10(6-exp);
66}
67
68/*
69VTF format uses exponent and variable size format.
70For example if the size is 2 bytes
710x0067 with VTF16E14 format -> +1.03
72To convert just change to 0x67 to decimal and use two decimal as E14 stands
73for 10^-2.
74Negative numbers are 2's complement
75*/
76static void convert_from_vtf_format(u32 value, int size, int exp,
77 int *val1, int *val2)
78{
79 int sign = 1;
80
81 if (value & BIT(size*8 - 1)) {
82 value = ((1LL << (size * 8)) - value);
83 sign = -1;
84 }
85 exp = hid_sensor_convert_exponent(exp);
86 if (exp >= 0) {
87 *val1 = sign * value * pow_10(exp);
88 *val2 = 0;
89 } else {
90 split_micro_fraction(value, -exp, val1, val2);
91 if (*val1)
92 *val1 = sign * (*val1);
93 else
94 *val2 = sign * (*val2);
95 }
96}
97
98static u32 convert_to_vtf_format(int size, int exp, int val1, int val2)
99{
100 u32 value;
101 int sign = 1;
102
103 if (val1 < 0 || val2 < 0)
104 sign = -1;
105 exp = hid_sensor_convert_exponent(exp);
106 if (exp < 0) {
107 value = abs(val1) * pow_10(-exp);
108 value += abs(val2) / pow_10(6+exp);
109 } else
110 value = abs(val1) / pow_10(exp);
111 if (sign < 0)
112 value = ((1LL << (size * 8)) - value);
113
114 return value;
115}
116
117int hid_sensor_read_samp_freq_value(struct hid_sensor_iio_common *st,
118 int *val1, int *val2)
119{
120 s32 value;
121 int ret;
122
123 ret = sensor_hub_get_feature(st->hsdev,
124 st->poll.report_id,
125 st->poll.index, &value);
126 if (ret < 0 || value < 0) {
127 *val1 = *val2 = 0;
128 return -EINVAL;
129 } else {
130 if (st->poll.units == HID_USAGE_SENSOR_UNITS_MILLISECOND)
131 simple_div(1000, value, val1, val2);
132 else if (st->poll.units == HID_USAGE_SENSOR_UNITS_SECOND)
133 simple_div(1, value, val1, val2);
134 else {
135 *val1 = *val2 = 0;
136 return -EINVAL;
137 }
138 }
139
140 return IIO_VAL_INT_PLUS_MICRO;
141}
142EXPORT_SYMBOL(hid_sensor_read_samp_freq_value);
143
144int hid_sensor_write_samp_freq_value(struct hid_sensor_iio_common *st,
145 int val1, int val2)
146{
147 s32 value;
148 int ret;
149
150 if (val1 < 0 || val2 < 0)
151 ret = -EINVAL;
152
153 value = val1 * pow_10(6) + val2;
154 if (value) {
155 if (st->poll.units == HID_USAGE_SENSOR_UNITS_MILLISECOND)
156 value = pow_10(9)/value;
157 else if (st->poll.units == HID_USAGE_SENSOR_UNITS_SECOND)
158 value = pow_10(6)/value;
159 else
160 value = 0;
161 }
162 ret = sensor_hub_set_feature(st->hsdev,
163 st->poll.report_id,
164 st->poll.index, value);
165 if (ret < 0 || value < 0)
166 ret = -EINVAL;
167
168 return ret;
169}
170EXPORT_SYMBOL(hid_sensor_write_samp_freq_value);
171
172int hid_sensor_read_raw_hyst_value(struct hid_sensor_iio_common *st,
173 int *val1, int *val2)
174{
175 s32 value;
176 int ret;
177
178 ret = sensor_hub_get_feature(st->hsdev,
179 st->sensitivity.report_id,
180 st->sensitivity.index, &value);
181 if (ret < 0 || value < 0) {
182 *val1 = *val2 = 0;
183 return -EINVAL;
184 } else {
185 convert_from_vtf_format(value, st->sensitivity.size,
186 st->sensitivity.unit_expo,
187 val1, val2);
188 }
189
190 return IIO_VAL_INT_PLUS_MICRO;
191}
192EXPORT_SYMBOL(hid_sensor_read_raw_hyst_value);
193
194int hid_sensor_write_raw_hyst_value(struct hid_sensor_iio_common *st,
195 int val1, int val2)
196{
197 s32 value;
198 int ret;
199
200 value = convert_to_vtf_format(st->sensitivity.size,
201 st->sensitivity.unit_expo,
202 val1, val2);
203 ret = sensor_hub_set_feature(st->hsdev,
204 st->sensitivity.report_id,
205 st->sensitivity.index, value);
206 if (ret < 0 || value < 0)
207 ret = -EINVAL;
208
209 return ret;
210}
211EXPORT_SYMBOL(hid_sensor_write_raw_hyst_value);
212
213int hid_sensor_parse_common_attributes(struct hid_sensor_hub_device *hsdev,
214 u32 usage_id,
215 struct hid_sensor_iio_common *st)
216{
217
218 sensor_hub_input_get_attribute_info(hsdev,
219 HID_FEATURE_REPORT, usage_id,
220 HID_USAGE_SENSOR_PROP_REPORT_INTERVAL,
221 &st->poll);
222
223 sensor_hub_input_get_attribute_info(hsdev,
224 HID_FEATURE_REPORT, usage_id,
225 HID_USAGE_SENSOR_PROP_REPORT_STATE,
226 &st->report_state);
227
228 sensor_hub_input_get_attribute_info(hsdev,
229 HID_FEATURE_REPORT, usage_id,
230 HID_USAGE_SENSOR_PROY_POWER_STATE,
231 &st->power_state);
232
233 sensor_hub_input_get_attribute_info(hsdev,
234 HID_FEATURE_REPORT, usage_id,
235 HID_USAGE_SENSOR_PROP_SENSITIVITY_ABS,
236 &st->sensitivity);
237
238 hid_dbg(hsdev->hdev, "common attributes: %x:%x, %x:%x, %x:%x %x:%x\n",
239 st->poll.index, st->poll.report_id,
240 st->report_state.index, st->report_state.report_id,
241 st->power_state.index, st->power_state.report_id,
242 st->sensitivity.index, st->sensitivity.report_id);
243
244 return 0;
245}
246EXPORT_SYMBOL(hid_sensor_parse_common_attributes);
247
248MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@intel.com>");
249MODULE_DESCRIPTION("HID Sensor common attribute processing");
250MODULE_LICENSE("GPL");
diff --git a/drivers/iio/common/hid-sensors/hid-sensor-attributes.h b/drivers/iio/common/hid-sensors/hid-sensor-attributes.h
new file mode 100644
index 000000000000..a4676a0c3de5
--- /dev/null
+++ b/drivers/iio/common/hid-sensors/hid-sensor-attributes.h
@@ -0,0 +1,57 @@
1/*
2 * HID Sensors Driver
3 * Copyright (c) 2012, Intel Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
17 *
18 */
19#ifndef _HID_SENSORS_ATTRIBUTES_H
20#define _HID_SENSORS_ATTRIBUTES_H
21
22/* Common hid sensor iio structure */
23struct hid_sensor_iio_common {
24 struct hid_sensor_hub_device *hsdev;
25 struct platform_device *pdev;
26 unsigned usage_id;
27 bool data_ready;
28 struct hid_sensor_hub_attribute_info poll;
29 struct hid_sensor_hub_attribute_info report_state;
30 struct hid_sensor_hub_attribute_info power_state;
31 struct hid_sensor_hub_attribute_info sensitivity;
32};
33
34/*Convert from hid unit expo to regular exponent*/
35static inline int hid_sensor_convert_exponent(int unit_expo)
36{
37 if (unit_expo < 0x08)
38 return unit_expo;
39 else if (unit_expo <= 0x0f)
40 return -(0x0f-unit_expo+1);
41 else
42 return 0;
43}
44
45int hid_sensor_parse_common_attributes(struct hid_sensor_hub_device *hsdev,
46 u32 usage_id,
47 struct hid_sensor_iio_common *st);
48int hid_sensor_write_raw_hyst_value(struct hid_sensor_iio_common *st,
49 int val1, int val2);
50int hid_sensor_read_raw_hyst_value(struct hid_sensor_iio_common *st,
51 int *val1, int *val2);
52int hid_sensor_write_samp_freq_value(struct hid_sensor_iio_common *st,
53 int val1, int val2);
54int hid_sensor_read_samp_freq_value(struct hid_sensor_iio_common *st,
55 int *val1, int *val2);
56
57#endif
diff --git a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
new file mode 100644
index 000000000000..12277e8bbd80
--- /dev/null
+++ b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
@@ -0,0 +1,102 @@
1/*
2 * HID Sensors Driver
3 * Copyright (c) 2012, Intel Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
17 *
18 */
19#include <linux/device.h>
20#include <linux/platform_device.h>
21#include <linux/module.h>
22#include <linux/interrupt.h>
23#include <linux/irq.h>
24#include <linux/slab.h>
25#include <linux/hid-sensor-hub.h>
26#include <linux/iio/iio.h>
27#include <linux/iio/trigger.h>
28#include <linux/iio/sysfs.h>
29#include "hid-sensor-attributes.h"
30#include "hid-sensor-trigger.h"
31
32static int hid_sensor_data_rdy_trigger_set_state(struct iio_trigger *trig,
33 bool state)
34{
35 struct hid_sensor_iio_common *st = trig->private_data;
36 int state_val;
37
38 state_val = state ? 1 : 0;
39#if (defined CONFIG_HID_SENSOR_ENUM_BASE_QUIRKS) || \
40 (defined CONFIG_HID_SENSOR_ENUM_BASE_QUIRKS_MODULE)
41 ++state_val;
42#endif
43 st->data_ready = state;
44 sensor_hub_set_feature(st->hsdev, st->power_state.report_id,
45 st->power_state.index,
46 (s32)state_val);
47
48 sensor_hub_set_feature(st->hsdev, st->report_state.report_id,
49 st->report_state.index,
50 (s32)state_val);
51
52 return 0;
53}
54
55void hid_sensor_remove_trigger(struct iio_dev *indio_dev)
56{
57 iio_trigger_unregister(indio_dev->trig);
58 iio_trigger_free(indio_dev->trig);
59}
60EXPORT_SYMBOL(hid_sensor_remove_trigger);
61
62static const struct iio_trigger_ops hid_sensor_trigger_ops = {
63 .owner = THIS_MODULE,
64 .set_trigger_state = &hid_sensor_data_rdy_trigger_set_state,
65};
66
67int hid_sensor_setup_trigger(struct iio_dev *indio_dev, const char *name,
68 struct hid_sensor_iio_common *attrb)
69{
70 int ret;
71 struct iio_trigger *trig;
72
73 trig = iio_trigger_alloc("%s-dev%d", name, indio_dev->id);
74 if (trig == NULL) {
75 dev_err(&indio_dev->dev, "Trigger Allocate Failed\n");
76 ret = -ENOMEM;
77 goto error_ret;
78 }
79
80 trig->dev.parent = indio_dev->dev.parent;
81 trig->private_data = attrb;
82 trig->ops = &hid_sensor_trigger_ops;
83 ret = iio_trigger_register(trig);
84
85 if (ret) {
86 dev_err(&indio_dev->dev, "Trigger Register Failed\n");
87 goto error_free_trig;
88 }
89 indio_dev->trig = trig;
90
91 return ret;
92
93error_free_trig:
94 iio_trigger_free(trig);
95error_ret:
96 return ret;
97}
98EXPORT_SYMBOL(hid_sensor_setup_trigger);
99
100MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@intel.com>");
101MODULE_DESCRIPTION("HID Sensor trigger processing");
102MODULE_LICENSE("GPL");
diff --git a/drivers/iio/common/hid-sensors/hid-sensor-trigger.h b/drivers/iio/common/hid-sensors/hid-sensor-trigger.h
new file mode 100644
index 000000000000..fd982971b1b8
--- /dev/null
+++ b/drivers/iio/common/hid-sensors/hid-sensor-trigger.h
@@ -0,0 +1,26 @@
1/*
2 * HID Sensors Driver
3 * Copyright (c) 2012, Intel Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
17 *
18 */
19#ifndef _HID_SENSOR_TRIGGER_H
20#define _HID_SENSOR_TRIGGER_H
21
22int hid_sensor_setup_trigger(struct iio_dev *indio_dev, const char *name,
23 struct hid_sensor_iio_common *attrb);
24void hid_sensor_remove_trigger(struct iio_dev *indio_dev);
25
26#endif