diff options
author | Lars-Peter Clausen <lars@metafoo.de> | 2012-09-17 08:17:00 -0400 |
---|---|---|
committer | Jonathan Cameron <jic23@kernel.org> | 2012-09-17 16:48:51 -0400 |
commit | 48e44ce0f8810b530fc83a4f5eb67149280d9b82 (patch) | |
tree | ce32b7a0917edb95fe5b4c3de1edd33e8d0f7ed6 /drivers/iio | |
parent | 45f010baa0292c367168b1f62d5494965b905b5d (diff) |
iio:inkern: Add function to read the processed value
Add a function to read a processed value from a channel. The function will first
attempt to read the IIO_CHAN_INFO_PROCESSED attribute. If that fails it will
read the IIO_CHAN_INFO_RAW attribute and convert the result from a raw value to
a processed value.
The patch also introduces a function to convert raw value to a processed value
and exports it, in case a user needs or wants to do the conversion by itself.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>
Diffstat (limited to 'drivers/iio')
-rw-r--r-- | drivers/iio/inkern.c | 118 |
1 files changed, 109 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 | ||