aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iio
diff options
context:
space:
mode:
authorLars-Peter Clausen <lars@metafoo.de>2012-09-17 08:17:00 -0400
committerJonathan Cameron <jic23@kernel.org>2012-09-17 16:48:51 -0400
commit48e44ce0f8810b530fc83a4f5eb67149280d9b82 (patch)
treece32b7a0917edb95fe5b4c3de1edd33e8d0f7ed6 /drivers/iio
parent45f010baa0292c367168b1f62d5494965b905b5d (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.c118
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}
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