aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/iio/inkern.c118
-rw-r--r--include/linux/iio/consumer.h38
-rw-r--r--include/linux/iio/iio.h17
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}
239EXPORT_SYMBOL_GPL(iio_channel_release_all); 239EXPORT_SYMBOL_GPL(iio_channel_release_all);
240 240
241static 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
241int iio_read_channel_raw(struct iio_channel *chan, int *val) 253int 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);
255err_unlock: 264err_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}
260EXPORT_SYMBOL_GPL(iio_read_channel_raw); 269EXPORT_SYMBOL_GPL(iio_read_channel_raw);
261 270
271static 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
318int 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);
331err_unlock:
332 mutex_unlock(&chan->indio_dev->info_exist_lock);
333
334 return ret;
335}
336EXPORT_SYMBOL_GPL(iio_convert_raw_to_processed);
337
338int 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
358err_unlock:
359 mutex_unlock(&chan->indio_dev->info_exist_lock);
360
361 return ret;
362}
363EXPORT_SYMBOL_GPL(iio_read_channel_processed);
364
262int iio_read_channel_scale(struct iio_channel *chan, int *val, int *val2) 365int 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);
276err_unlock: 376err_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 */
86int 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,
93int iio_read_channel_scale(struct iio_channel *chan, int *val, 108int 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 */
131int 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 */
275static 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