diff options
-rw-r--r-- | drivers/iio/inkern.c | 118 | ||||
-rw-r--r-- | include/linux/iio/consumer.h | 38 | ||||
-rw-r--r-- | include/linux/iio/iio.h | 17 |
3 files changed, 164 insertions, 9 deletions
diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c index d539e1e297ba..25b00761005a 100644 --- a/drivers/iio/inkern.c +++ b/drivers/iio/inkern.c | |||
@@ -238,9 +238,21 @@ void iio_channel_release_all(struct iio_channel *channels) | |||
238 | } | 238 | } |
239 | EXPORT_SYMBOL_GPL(iio_channel_release_all); | 239 | EXPORT_SYMBOL_GPL(iio_channel_release_all); |
240 | 240 | ||
241 | static int iio_channel_read(struct iio_channel *chan, int *val, int *val2, | ||
242 | enum iio_chan_info_enum info) | ||
243 | { | ||
244 | int unused; | ||
245 | |||
246 | if (val2 == NULL) | ||
247 | val2 = &unused; | ||
248 | |||
249 | return chan->indio_dev->info->read_raw(chan->indio_dev, chan->channel, | ||
250 | val, val2, info); | ||
251 | } | ||
252 | |||
241 | int iio_read_channel_raw(struct iio_channel *chan, int *val) | 253 | int iio_read_channel_raw(struct iio_channel *chan, int *val) |
242 | { | 254 | { |
243 | int val2, ret; | 255 | int ret; |
244 | 256 | ||
245 | mutex_lock(&chan->indio_dev->info_exist_lock); | 257 | mutex_lock(&chan->indio_dev->info_exist_lock); |
246 | if (chan->indio_dev->info == NULL) { | 258 | if (chan->indio_dev->info == NULL) { |
@@ -248,10 +260,7 @@ int iio_read_channel_raw(struct iio_channel *chan, int *val) | |||
248 | goto err_unlock; | 260 | goto err_unlock; |
249 | } | 261 | } |
250 | 262 | ||
251 | ret = chan->indio_dev->info->read_raw(chan->indio_dev, | 263 | ret = iio_channel_read(chan, val, NULL, IIO_CHAN_INFO_RAW); |
252 | chan->channel, | ||
253 | val, &val2, | ||
254 | IIO_CHAN_INFO_RAW); | ||
255 | err_unlock: | 264 | err_unlock: |
256 | mutex_unlock(&chan->indio_dev->info_exist_lock); | 265 | mutex_unlock(&chan->indio_dev->info_exist_lock); |
257 | 266 | ||
@@ -259,6 +268,100 @@ err_unlock: | |||
259 | } | 268 | } |
260 | EXPORT_SYMBOL_GPL(iio_read_channel_raw); | 269 | EXPORT_SYMBOL_GPL(iio_read_channel_raw); |
261 | 270 | ||
271 | static int iio_convert_raw_to_processed_unlocked(struct iio_channel *chan, | ||
272 | int raw, int *processed, unsigned int scale) | ||
273 | { | ||
274 | int scale_type, scale_val, scale_val2, offset; | ||
275 | s64 raw64 = raw; | ||
276 | int ret; | ||
277 | |||
278 | ret = iio_channel_read(chan, &offset, NULL, IIO_CHAN_INFO_SCALE); | ||
279 | if (ret == 0) | ||
280 | raw64 += offset; | ||
281 | |||
282 | scale_type = iio_channel_read(chan, &scale_val, &scale_val2, | ||
283 | IIO_CHAN_INFO_SCALE); | ||
284 | if (scale_type < 0) | ||
285 | return scale_type; | ||
286 | |||
287 | switch (scale_type) { | ||
288 | case IIO_VAL_INT: | ||
289 | *processed = raw64 * scale_val; | ||
290 | break; | ||
291 | case IIO_VAL_INT_PLUS_MICRO: | ||
292 | if (scale_val2 < 0) | ||
293 | *processed = -raw64 * scale_val; | ||
294 | else | ||
295 | *processed = raw64 * scale_val; | ||
296 | *processed += div_s64(raw64 * (s64)scale_val2 * scale, | ||
297 | 1000000LL); | ||
298 | break; | ||
299 | case IIO_VAL_INT_PLUS_NANO: | ||
300 | if (scale_val2 < 0) | ||
301 | *processed = -raw64 * scale_val; | ||
302 | else | ||
303 | *processed = raw64 * scale_val; | ||
304 | *processed += div_s64(raw64 * (s64)scale_val2 * scale, | ||
305 | 1000000000LL); | ||
306 | break; | ||
307 | case IIO_VAL_FRACTIONAL: | ||
308 | *processed = div_s64(raw64 * (s64)scale_val * scale, | ||
309 | scale_val2); | ||
310 | break; | ||
311 | default: | ||
312 | return -EINVAL; | ||
313 | } | ||
314 | |||
315 | return 0; | ||
316 | } | ||
317 | |||
318 | int iio_convert_raw_to_processed(struct iio_channel *chan, int raw, | ||
319 | int *processed, unsigned int scale) | ||
320 | { | ||
321 | int ret; | ||
322 | |||
323 | mutex_lock(&chan->indio_dev->info_exist_lock); | ||
324 | if (chan->indio_dev->info == NULL) { | ||
325 | ret = -ENODEV; | ||
326 | goto err_unlock; | ||
327 | } | ||
328 | |||
329 | ret = iio_convert_raw_to_processed_unlocked(chan, raw, processed, | ||
330 | scale); | ||
331 | err_unlock: | ||
332 | mutex_unlock(&chan->indio_dev->info_exist_lock); | ||
333 | |||
334 | return ret; | ||
335 | } | ||
336 | EXPORT_SYMBOL_GPL(iio_convert_raw_to_processed); | ||
337 | |||
338 | int iio_read_channel_processed(struct iio_channel *chan, int *val) | ||
339 | { | ||
340 | int ret; | ||
341 | |||
342 | mutex_lock(&chan->indio_dev->info_exist_lock); | ||
343 | if (chan->indio_dev->info == NULL) { | ||
344 | ret = -ENODEV; | ||
345 | goto err_unlock; | ||
346 | } | ||
347 | |||
348 | if (iio_channel_has_info(chan->channel, IIO_CHAN_INFO_PROCESSED)) { | ||
349 | ret = iio_channel_read(chan, val, NULL, | ||
350 | IIO_CHAN_INFO_PROCESSED); | ||
351 | } else { | ||
352 | ret = iio_channel_read(chan, val, NULL, IIO_CHAN_INFO_RAW); | ||
353 | if (ret < 0) | ||
354 | goto err_unlock; | ||
355 | ret = iio_convert_raw_to_processed_unlocked(chan, *val, val, 1); | ||
356 | } | ||
357 | |||
358 | err_unlock: | ||
359 | mutex_unlock(&chan->indio_dev->info_exist_lock); | ||
360 | |||
361 | return ret; | ||
362 | } | ||
363 | EXPORT_SYMBOL_GPL(iio_read_channel_processed); | ||
364 | |||
262 | int iio_read_channel_scale(struct iio_channel *chan, int *val, int *val2) | 365 | int iio_read_channel_scale(struct iio_channel *chan, int *val, int *val2) |
263 | { | 366 | { |
264 | int ret; | 367 | int ret; |
@@ -269,10 +372,7 @@ int iio_read_channel_scale(struct iio_channel *chan, int *val, int *val2) | |||
269 | goto err_unlock; | 372 | goto err_unlock; |
270 | } | 373 | } |
271 | 374 | ||
272 | ret = chan->indio_dev->info->read_raw(chan->indio_dev, | 375 | ret = iio_channel_read(chan, val, val2, IIO_CHAN_INFO_SCALE); |
273 | chan->channel, | ||
274 | val, val2, | ||
275 | IIO_CHAN_INFO_SCALE); | ||
276 | err_unlock: | 376 | err_unlock: |
277 | mutex_unlock(&chan->indio_dev->info_exist_lock); | 377 | mutex_unlock(&chan->indio_dev->info_exist_lock); |
278 | 378 | ||
diff --git a/include/linux/iio/consumer.h b/include/linux/iio/consumer.h index 62118dd707d7..e875bcf0478f 100644 --- a/include/linux/iio/consumer.h +++ b/include/linux/iio/consumer.h | |||
@@ -71,6 +71,21 @@ int iio_read_channel_raw(struct iio_channel *chan, | |||
71 | int *val); | 71 | int *val); |
72 | 72 | ||
73 | /** | 73 | /** |
74 | * iio_read_channel_processed() - read processed value from a given channel | ||
75 | * @chan: The channel being queried. | ||
76 | * @val: Value read back. | ||
77 | * | ||
78 | * Returns an error code or 0. | ||
79 | * | ||
80 | * This function will read a processed value from a channel. A processed value | ||
81 | * means that this value will have the correct unit and not some device internal | ||
82 | * representation. If the device does not support reporting a processed value | ||
83 | * the function will query the raw value and the channels scale and offset and | ||
84 | * do the appropriate transformation. | ||
85 | */ | ||
86 | int iio_read_channel_processed(struct iio_channel *chan, int *val); | ||
87 | |||
88 | /** | ||
74 | * iio_get_channel_type() - get the type of a channel | 89 | * iio_get_channel_type() - get the type of a channel |
75 | * @channel: The channel being queried. | 90 | * @channel: The channel being queried. |
76 | * @type: The type of the channel. | 91 | * @type: The type of the channel. |
@@ -93,4 +108,27 @@ int iio_get_channel_type(struct iio_channel *channel, | |||
93 | int iio_read_channel_scale(struct iio_channel *chan, int *val, | 108 | int iio_read_channel_scale(struct iio_channel *chan, int *val, |
94 | int *val2); | 109 | int *val2); |
95 | 110 | ||
111 | /** | ||
112 | * iio_convert_raw_to_processed() - Converts a raw value to a processed value | ||
113 | * @chan: The channel being queried | ||
114 | * @raw: The raw IIO to convert | ||
115 | * @processed: The result of the conversion | ||
116 | * @scale: Scale factor to apply during the conversion | ||
117 | * | ||
118 | * Returns an error code or 0. | ||
119 | * | ||
120 | * This function converts a raw value to processed value for a specific channel. | ||
121 | * A raw value is the device internal representation of a sample and the value | ||
122 | * returned by iio_read_channel_raw, so the unit of that value is device | ||
123 | * depended. A processed value on the other hand is value has a normed unit | ||
124 | * according with the IIO specification. | ||
125 | * | ||
126 | * The scale factor allows to increase the precession of the returned value. For | ||
127 | * a scale factor of 1 the function will return the result in the normal IIO | ||
128 | * unit for the channel type. E.g. millivolt for voltage channels, if you want | ||
129 | * nanovolts instead pass 1000 as the scale factor. | ||
130 | */ | ||
131 | int iio_convert_raw_to_processed(struct iio_channel *chan, int raw, | ||
132 | int *processed, unsigned int scale); | ||
133 | |||
96 | #endif | 134 | #endif |
diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index 30affa533a1f..c0ae76ac4e0b 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h | |||
@@ -40,6 +40,8 @@ enum iio_chan_info_enum { | |||
40 | 40 | ||
41 | #define IIO_CHAN_INFO_SHARED_BIT(type) BIT(type*2) | 41 | #define IIO_CHAN_INFO_SHARED_BIT(type) BIT(type*2) |
42 | #define IIO_CHAN_INFO_SEPARATE_BIT(type) BIT(type*2 + 1) | 42 | #define IIO_CHAN_INFO_SEPARATE_BIT(type) BIT(type*2 + 1) |
43 | #define IIO_CHAN_INFO_BITS(type) (IIO_CHAN_INFO_SHARED_BIT(type) | \ | ||
44 | IIO_CHAN_INFO_SEPARATE_BIT(type)) | ||
43 | 45 | ||
44 | #define IIO_CHAN_INFO_RAW_SEPARATE_BIT \ | 46 | #define IIO_CHAN_INFO_RAW_SEPARATE_BIT \ |
45 | IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_RAW) | 47 | IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_RAW) |
@@ -261,6 +263,21 @@ struct iio_chan_spec { | |||
261 | unsigned differential:1; | 263 | unsigned differential:1; |
262 | }; | 264 | }; |
263 | 265 | ||
266 | |||
267 | /** | ||
268 | * iio_channel_has_info() - Checks whether a channel supports a info attribute | ||
269 | * @chan: The channel to be queried | ||
270 | * @type: Type of the info attribute to be checked | ||
271 | * | ||
272 | * Returns true if the channels supports reporting values for the given info | ||
273 | * attribute type, false otherwise. | ||
274 | */ | ||
275 | static inline bool iio_channel_has_info(const struct iio_chan_spec *chan, | ||
276 | enum iio_chan_info_enum type) | ||
277 | { | ||
278 | return chan->info_mask & IIO_CHAN_INFO_BITS(type); | ||
279 | } | ||
280 | |||
264 | #define IIO_ST(si, rb, sb, sh) \ | 281 | #define IIO_ST(si, rb, sb, sh) \ |
265 | { .sign = si, .realbits = rb, .storagebits = sb, .shift = sh } | 282 | { .sign = si, .realbits = rb, .storagebits = sb, .shift = sh } |
266 | 283 | ||