diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-03 11:34:00 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-03 11:34:00 -0400 |
commit | 5142c33ed86acbcef5c63a63d2b7384b9210d39f (patch) | |
tree | 6a0a36207ab436e1ef03bfefa7dac8f3a0cdfae5 /drivers/iio/common/hid-sensors | |
parent | 5da77761e6fd51f633b4f31051c4f839e01c29c0 (diff) | |
parent | 7eb843aa5050a395bc922db1b41b7237f238d2ba (diff) |
Merge tag 'staging-3.16-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging into next
Pull staging driver updates from Greg KH:
"Here is the big staging driver pull request for 3.16-rc1.
Lots of stuff here, tons of cleanup patches, a few new drivers, and
some removed as well, but I think we are still adding a few thousand
more lines than we remove, due to the new drivers being bigger than
the ones deleted.
One notible bit of work did stand out, Jes Sorensen has gone on a
tear, fixing up a wireless driver to be "more sane" than it originally
was from the vendor, with over 500 patches merged here. Good stuff,
and a number of users laptops are better off for it.
All of this has been in linux-next for a while"
* tag 'staging-3.16-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging: (1703 commits)
staging: skein: fix sparse warning for static declarations
staging/mt29f_spinand: coding style fixes
staging: silicom: fix sparse warning for static variable
staging: lustre: Fix coding style
staging: android: binder.c: Use more appropriate functions for euid retrieval
staging: lustre: fix integer as NULL pointer warnings
Revert "staging: dgap: remove unneeded kfree() in dgap_tty_register_ports()"
Staging: rtl8192u: r8192U_wx.c Fixed a misplaced brace
staging: ion: shrink highmem pages on kswapd
staging: ion: use compound pages on high order pages for system heap
staging: ion: remove struct ion_page_pool_item
staging: ion: simplify ion_page_pool_total()
staging: ion: tidy up a bit
staging: rtl8723au: Remove redundant casting in usb_ops_linux.c
staging: rtl8723au: Remove redundant casting in rtl8723a_hal_init.c
staging: rtl8723au: Remove redundant casting in rtw_xmit.c
staging: rtl8723au: Remove redundant casting in rtw_wlan_util.c
staging: rtl8723au: Remove redundant casting in rtw_sta_mgt.c
staging: rtl8723au: Remove redundant casting in rtw_recv.c
staging: rtl8723au: Remove redundant casting in rtw_mlme.c
...
Diffstat (limited to 'drivers/iio/common/hid-sensors')
-rw-r--r-- | drivers/iio/common/hid-sensors/hid-sensor-attributes.c | 151 | ||||
-rw-r--r-- | drivers/iio/common/hid-sensors/hid-sensor-trigger.c | 17 | ||||
-rw-r--r-- | drivers/iio/common/hid-sensors/hid-sensor-trigger.h | 1 |
3 files changed, 163 insertions, 6 deletions
diff --git a/drivers/iio/common/hid-sensors/hid-sensor-attributes.c b/drivers/iio/common/hid-sensors/hid-sensor-attributes.c index 75b54730a963..403dd3d8986e 100644 --- a/drivers/iio/common/hid-sensors/hid-sensor-attributes.c +++ b/drivers/iio/common/hid-sensors/hid-sensor-attributes.c | |||
@@ -26,6 +26,40 @@ | |||
26 | #include <linux/iio/iio.h> | 26 | #include <linux/iio/iio.h> |
27 | #include <linux/iio/sysfs.h> | 27 | #include <linux/iio/sysfs.h> |
28 | 28 | ||
29 | struct { | ||
30 | u32 usage_id; | ||
31 | int unit; /* 0 for default others from HID sensor spec */ | ||
32 | int scale_val0; /* scale, whole number */ | ||
33 | int scale_val1; /* scale, fraction in micros */ | ||
34 | } static unit_conversion[] = { | ||
35 | {HID_USAGE_SENSOR_ACCEL_3D, 0, 9, 806650}, | ||
36 | {HID_USAGE_SENSOR_ACCEL_3D, | ||
37 | HID_USAGE_SENSOR_UNITS_METERS_PER_SEC_SQRD, 1, 0}, | ||
38 | {HID_USAGE_SENSOR_ACCEL_3D, | ||
39 | HID_USAGE_SENSOR_UNITS_G, 9, 806650}, | ||
40 | |||
41 | {HID_USAGE_SENSOR_GYRO_3D, 0, 0, 17453}, | ||
42 | {HID_USAGE_SENSOR_GYRO_3D, | ||
43 | HID_USAGE_SENSOR_UNITS_RADIANS_PER_SECOND, 1, 0}, | ||
44 | {HID_USAGE_SENSOR_GYRO_3D, | ||
45 | HID_USAGE_SENSOR_UNITS_DEGREES_PER_SECOND, 0, 17453}, | ||
46 | |||
47 | {HID_USAGE_SENSOR_COMPASS_3D, 0, 0, 1000}, | ||
48 | {HID_USAGE_SENSOR_COMPASS_3D, HID_USAGE_SENSOR_UNITS_GAUSS, 1, 0}, | ||
49 | |||
50 | {HID_USAGE_SENSOR_INCLINOMETER_3D, 0, 0, 17453}, | ||
51 | {HID_USAGE_SENSOR_INCLINOMETER_3D, | ||
52 | HID_USAGE_SENSOR_UNITS_DEGREES, 0, 17453}, | ||
53 | {HID_USAGE_SENSOR_INCLINOMETER_3D, | ||
54 | HID_USAGE_SENSOR_UNITS_RADIANS, 1, 0}, | ||
55 | |||
56 | {HID_USAGE_SENSOR_ALS, 0, 1, 0}, | ||
57 | {HID_USAGE_SENSOR_ALS, HID_USAGE_SENSOR_UNITS_LUX, 1, 0}, | ||
58 | |||
59 | {HID_USAGE_SENSOR_PRESSURE, 0, 100000, 0}, | ||
60 | {HID_USAGE_SENSOR_PRESSURE, HID_USAGE_SENSOR_UNITS_PASCAL, 1, 0}, | ||
61 | }; | ||
62 | |||
29 | static int pow_10(unsigned power) | 63 | static int pow_10(unsigned power) |
30 | { | 64 | { |
31 | int i; | 65 | int i; |
@@ -113,6 +147,26 @@ static u32 convert_to_vtf_format(int size, int exp, int val1, int val2) | |||
113 | return value; | 147 | return value; |
114 | } | 148 | } |
115 | 149 | ||
150 | s32 hid_sensor_read_poll_value(struct hid_sensor_common *st) | ||
151 | { | ||
152 | s32 value = 0; | ||
153 | int ret; | ||
154 | |||
155 | ret = sensor_hub_get_feature(st->hsdev, | ||
156 | st->poll.report_id, | ||
157 | st->poll.index, &value); | ||
158 | |||
159 | if (ret < 0 || value < 0) { | ||
160 | return -EINVAL; | ||
161 | } else { | ||
162 | if (st->poll.units == HID_USAGE_SENSOR_UNITS_SECOND) | ||
163 | value = value * 1000; | ||
164 | } | ||
165 | |||
166 | return value; | ||
167 | } | ||
168 | EXPORT_SYMBOL(hid_sensor_read_poll_value); | ||
169 | |||
116 | int hid_sensor_read_samp_freq_value(struct hid_sensor_common *st, | 170 | int hid_sensor_read_samp_freq_value(struct hid_sensor_common *st, |
117 | int *val1, int *val2) | 171 | int *val1, int *val2) |
118 | { | 172 | { |
@@ -209,15 +263,108 @@ int hid_sensor_write_raw_hyst_value(struct hid_sensor_common *st, | |||
209 | } | 263 | } |
210 | EXPORT_SYMBOL(hid_sensor_write_raw_hyst_value); | 264 | EXPORT_SYMBOL(hid_sensor_write_raw_hyst_value); |
211 | 265 | ||
212 | int hid_sensor_parse_common_attributes(struct hid_sensor_hub_device *hsdev, | 266 | /* |
267 | * This fuction applies the unit exponent to the scale. | ||
268 | * For example: | ||
269 | * 9.806650 ->exp:2-> val0[980]val1[665000] | ||
270 | * 9.000806 ->exp:2-> val0[900]val1[80600] | ||
271 | * 0.174535 ->exp:2-> val0[17]val1[453500] | ||
272 | * 1.001745 ->exp:0-> val0[1]val1[1745] | ||
273 | * 1.001745 ->exp:2-> val0[100]val1[174500] | ||
274 | * 1.001745 ->exp:4-> val0[10017]val1[450000] | ||
275 | * 9.806650 ->exp:-2-> val0[0]val1[98066] | ||
276 | */ | ||
277 | static void adjust_exponent_micro(int *val0, int *val1, int scale0, | ||
278 | int scale1, int exp) | ||
279 | { | ||
280 | int i; | ||
281 | int x; | ||
282 | int res; | ||
283 | int rem; | ||
284 | |||
285 | if (exp > 0) { | ||
286 | *val0 = scale0 * pow_10(exp); | ||
287 | res = 0; | ||
288 | if (exp > 6) { | ||
289 | *val1 = 0; | ||
290 | return; | ||
291 | } | ||
292 | for (i = 0; i < exp; ++i) { | ||
293 | x = scale1 / pow_10(5 - i); | ||
294 | res += (pow_10(exp - 1 - i) * x); | ||
295 | scale1 = scale1 % pow_10(5 - i); | ||
296 | } | ||
297 | *val0 += res; | ||
298 | *val1 = scale1 * pow_10(exp); | ||
299 | } else if (exp < 0) { | ||
300 | exp = abs(exp); | ||
301 | if (exp > 6) { | ||
302 | *val0 = *val1 = 0; | ||
303 | return; | ||
304 | } | ||
305 | *val0 = scale0 / pow_10(exp); | ||
306 | rem = scale0 % pow_10(exp); | ||
307 | res = 0; | ||
308 | for (i = 0; i < (6 - exp); ++i) { | ||
309 | x = scale1 / pow_10(5 - i); | ||
310 | res += (pow_10(5 - exp - i) * x); | ||
311 | scale1 = scale1 % pow_10(5 - i); | ||
312 | } | ||
313 | *val1 = rem * pow_10(6 - exp) + res; | ||
314 | } else { | ||
315 | *val0 = scale0; | ||
316 | *val1 = scale1; | ||
317 | } | ||
318 | } | ||
319 | |||
320 | int hid_sensor_format_scale(u32 usage_id, | ||
321 | struct hid_sensor_hub_attribute_info *attr_info, | ||
322 | int *val0, int *val1) | ||
323 | { | ||
324 | int i; | ||
325 | int exp; | ||
326 | |||
327 | *val0 = 1; | ||
328 | *val1 = 0; | ||
329 | |||
330 | for (i = 0; i < ARRAY_SIZE(unit_conversion); ++i) { | ||
331 | if (unit_conversion[i].usage_id == usage_id && | ||
332 | unit_conversion[i].unit == attr_info->units) { | ||
333 | exp = hid_sensor_convert_exponent( | ||
334 | attr_info->unit_expo); | ||
335 | adjust_exponent_micro(val0, val1, | ||
336 | unit_conversion[i].scale_val0, | ||
337 | unit_conversion[i].scale_val1, exp); | ||
338 | break; | ||
339 | } | ||
340 | } | ||
341 | |||
342 | return IIO_VAL_INT_PLUS_MICRO; | ||
343 | } | ||
344 | EXPORT_SYMBOL(hid_sensor_format_scale); | ||
345 | |||
346 | int hid_sensor_get_reporting_interval(struct hid_sensor_hub_device *hsdev, | ||
213 | u32 usage_id, | 347 | u32 usage_id, |
214 | struct hid_sensor_common *st) | 348 | struct hid_sensor_common *st) |
215 | { | 349 | { |
216 | |||
217 | sensor_hub_input_get_attribute_info(hsdev, | 350 | sensor_hub_input_get_attribute_info(hsdev, |
218 | HID_FEATURE_REPORT, usage_id, | 351 | HID_FEATURE_REPORT, usage_id, |
219 | HID_USAGE_SENSOR_PROP_REPORT_INTERVAL, | 352 | HID_USAGE_SENSOR_PROP_REPORT_INTERVAL, |
220 | &st->poll); | 353 | &st->poll); |
354 | /* Default unit of measure is milliseconds */ | ||
355 | if (st->poll.units == 0) | ||
356 | st->poll.units = HID_USAGE_SENSOR_UNITS_MILLISECOND; | ||
357 | return 0; | ||
358 | |||
359 | } | ||
360 | |||
361 | int hid_sensor_parse_common_attributes(struct hid_sensor_hub_device *hsdev, | ||
362 | u32 usage_id, | ||
363 | struct hid_sensor_common *st) | ||
364 | { | ||
365 | |||
366 | |||
367 | hid_sensor_get_reporting_interval(hsdev, usage_id, st); | ||
221 | 368 | ||
222 | sensor_hub_input_get_attribute_info(hsdev, | 369 | sensor_hub_input_get_attribute_info(hsdev, |
223 | HID_FEATURE_REPORT, usage_id, | 370 | HID_FEATURE_REPORT, usage_id, |
diff --git a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c index dbefbdaf7cd1..73282cee0c81 100644 --- a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c +++ b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c | |||
@@ -28,16 +28,17 @@ | |||
28 | #include <linux/iio/sysfs.h> | 28 | #include <linux/iio/sysfs.h> |
29 | #include "hid-sensor-trigger.h" | 29 | #include "hid-sensor-trigger.h" |
30 | 30 | ||
31 | static int hid_sensor_data_rdy_trigger_set_state(struct iio_trigger *trig, | 31 | int hid_sensor_power_state(struct hid_sensor_common *st, bool state) |
32 | bool state) | ||
33 | { | 32 | { |
34 | struct hid_sensor_common *st = iio_trigger_get_drvdata(trig); | ||
35 | int state_val; | 33 | int state_val; |
36 | int report_val; | 34 | int report_val; |
37 | 35 | ||
38 | if (state) { | 36 | if (state) { |
39 | if (sensor_hub_device_open(st->hsdev)) | 37 | if (sensor_hub_device_open(st->hsdev)) |
40 | return -EIO; | 38 | return -EIO; |
39 | |||
40 | atomic_inc(&st->data_ready); | ||
41 | |||
41 | state_val = hid_sensor_get_usage_index(st->hsdev, | 42 | state_val = hid_sensor_get_usage_index(st->hsdev, |
42 | st->power_state.report_id, | 43 | st->power_state.report_id, |
43 | st->power_state.index, | 44 | st->power_state.index, |
@@ -47,6 +48,8 @@ static int hid_sensor_data_rdy_trigger_set_state(struct iio_trigger *trig, | |||
47 | st->report_state.index, | 48 | st->report_state.index, |
48 | HID_USAGE_SENSOR_PROP_REPORTING_STATE_ALL_EVENTS_ENUM); | 49 | HID_USAGE_SENSOR_PROP_REPORTING_STATE_ALL_EVENTS_ENUM); |
49 | } else { | 50 | } else { |
51 | if (!atomic_dec_and_test(&st->data_ready)) | ||
52 | return 0; | ||
50 | sensor_hub_device_close(st->hsdev); | 53 | sensor_hub_device_close(st->hsdev); |
51 | state_val = hid_sensor_get_usage_index(st->hsdev, | 54 | state_val = hid_sensor_get_usage_index(st->hsdev, |
52 | st->power_state.report_id, | 55 | st->power_state.report_id, |
@@ -57,7 +60,6 @@ static int hid_sensor_data_rdy_trigger_set_state(struct iio_trigger *trig, | |||
57 | st->report_state.index, | 60 | st->report_state.index, |
58 | HID_USAGE_SENSOR_PROP_REPORTING_STATE_NO_EVENTS_ENUM); | 61 | HID_USAGE_SENSOR_PROP_REPORTING_STATE_NO_EVENTS_ENUM); |
59 | } | 62 | } |
60 | st->data_ready = state; | ||
61 | 63 | ||
62 | if (state_val >= 0) { | 64 | if (state_val >= 0) { |
63 | state_val += st->power_state.logical_minimum; | 65 | state_val += st->power_state.logical_minimum; |
@@ -75,6 +77,13 @@ static int hid_sensor_data_rdy_trigger_set_state(struct iio_trigger *trig, | |||
75 | 77 | ||
76 | return 0; | 78 | return 0; |
77 | } | 79 | } |
80 | EXPORT_SYMBOL(hid_sensor_power_state); | ||
81 | |||
82 | static int hid_sensor_data_rdy_trigger_set_state(struct iio_trigger *trig, | ||
83 | bool state) | ||
84 | { | ||
85 | return hid_sensor_power_state(iio_trigger_get_drvdata(trig), state); | ||
86 | } | ||
78 | 87 | ||
79 | void hid_sensor_remove_trigger(struct hid_sensor_common *attrb) | 88 | void hid_sensor_remove_trigger(struct hid_sensor_common *attrb) |
80 | { | 89 | { |
diff --git a/drivers/iio/common/hid-sensors/hid-sensor-trigger.h b/drivers/iio/common/hid-sensors/hid-sensor-trigger.h index ca02f7811aa8..0f8e78c249d3 100644 --- a/drivers/iio/common/hid-sensors/hid-sensor-trigger.h +++ b/drivers/iio/common/hid-sensors/hid-sensor-trigger.h | |||
@@ -22,5 +22,6 @@ | |||
22 | int hid_sensor_setup_trigger(struct iio_dev *indio_dev, const char *name, | 22 | int hid_sensor_setup_trigger(struct iio_dev *indio_dev, const char *name, |
23 | struct hid_sensor_common *attrb); | 23 | struct hid_sensor_common *attrb); |
24 | void hid_sensor_remove_trigger(struct hid_sensor_common *attrb); | 24 | void hid_sensor_remove_trigger(struct hid_sensor_common *attrb); |
25 | int hid_sensor_power_state(struct hid_sensor_common *st, bool state); | ||
25 | 26 | ||
26 | #endif | 27 | #endif |