diff options
Diffstat (limited to 'drivers/iio/inkern.c')
-rw-r--r-- | drivers/iio/inkern.c | 86 |
1 files changed, 73 insertions, 13 deletions
diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c index 872fd5c24147..7a1f6713318a 100644 --- a/drivers/iio/inkern.c +++ b/drivers/iio/inkern.c @@ -5,9 +5,10 @@ */ #include <linux/err.h> #include <linux/export.h> +#include <linux/minmax.h> +#include <linux/mutex.h> #include <linux/property.h> #include <linux/slab.h> -#include <linux/mutex.h> #include <linux/iio/iio.h> #include <linux/iio/iio-opaque.h> @@ -849,15 +850,14 @@ static int iio_channel_read_max(struct iio_channel *chan, int *val, int *val2, int *type, enum iio_chan_info_enum info) { - int unused; const int *vals; int length; int ret; - if (!val2) - val2 = &unused; - ret = iio_channel_read_avail(chan, &vals, type, &length, info); + if (ret < 0) + return ret; + switch (ret) { case IIO_AVAIL_RANGE: switch (*type) { @@ -866,7 +866,8 @@ static int iio_channel_read_max(struct iio_channel *chan, break; default: *val = vals[4]; - *val2 = vals[5]; + if (val2) + *val2 = vals[5]; } return 0; @@ -875,20 +876,16 @@ static int iio_channel_read_max(struct iio_channel *chan, return -EINVAL; switch (*type) { case IIO_VAL_INT: - *val = vals[--length]; - while (length) { - if (vals[--length] > *val) - *val = vals[length]; - } + *val = max_array(vals, length); break; default: - /* FIXME: learn about max for other iio values */ + /* TODO: learn about max for other iio values */ return -EINVAL; } return 0; default: - return ret; + return -EINVAL; } } @@ -912,6 +909,69 @@ err_unlock: } EXPORT_SYMBOL_GPL(iio_read_max_channel_raw); +static int iio_channel_read_min(struct iio_channel *chan, + int *val, int *val2, int *type, + enum iio_chan_info_enum info) +{ + const int *vals; + int length; + int ret; + + ret = iio_channel_read_avail(chan, &vals, type, &length, info); + if (ret < 0) + return ret; + + switch (ret) { + case IIO_AVAIL_RANGE: + switch (*type) { + case IIO_VAL_INT: + *val = vals[0]; + break; + default: + *val = vals[0]; + if (val2) + *val2 = vals[1]; + } + return 0; + + case IIO_AVAIL_LIST: + if (length <= 0) + return -EINVAL; + switch (*type) { + case IIO_VAL_INT: + *val = min_array(vals, length); + break; + default: + /* TODO: learn about min for other iio values */ + return -EINVAL; + } + return 0; + + default: + return -EINVAL; + } +} + +int iio_read_min_channel_raw(struct iio_channel *chan, int *val) +{ + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(chan->indio_dev); + int ret; + int type; + + mutex_lock(&iio_dev_opaque->info_exist_lock); + if (!chan->indio_dev->info) { + ret = -ENODEV; + goto err_unlock; + } + + ret = iio_channel_read_min(chan, val, NULL, &type, IIO_CHAN_INFO_RAW); +err_unlock: + mutex_unlock(&iio_dev_opaque->info_exist_lock); + + return ret; +} +EXPORT_SYMBOL_GPL(iio_read_min_channel_raw); + int iio_get_channel_type(struct iio_channel *chan, enum iio_chan_type *type) { struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(chan->indio_dev); |