Message ID | 20230615152631.224529-11-herve.codina@bootlin.com (mailing list archive) |
---|---|
State | Changes Requested |
Headers | show |
Series | Add support for IIO devices in ASoC | expand |
On Thu, 15 Jun 2023 17:26:28 +0200 Herve Codina <herve.codina@bootlin.com> wrote: > A helper, iio_read_max_channel_raw() exists to read the available > maximum raw value of a channel but nothing similar exists to read the > available minimum raw value. > > This new helper, iio_read_min_channel_raw(), fills the hole and can be > used for reading the available minimum raw value of a channel. > It is fully based on the existing iio_read_max_channel_raw(). > > Signed-off-by: Herve Codina <herve.codina@bootlin.com> > Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com> LGTM Acked-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> > --- > drivers/iio/inkern.c | 63 ++++++++++++++++++++++++++++++++++++ > include/linux/iio/consumer.h | 12 +++++++ > 2 files changed, 75 insertions(+) > > diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c > index 19ddd77adb11..7a1f6713318a 100644 > --- a/drivers/iio/inkern.c > +++ b/drivers/iio/inkern.c > @@ -909,6 +909,69 @@ int iio_read_max_channel_raw(struct iio_channel *chan, int *val) > } > 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); > diff --git a/include/linux/iio/consumer.h b/include/linux/iio/consumer.h > index f536820b9cf2..e9910b41d48e 100644 > --- a/include/linux/iio/consumer.h > +++ b/include/linux/iio/consumer.h > @@ -301,6 +301,18 @@ int iio_write_channel_raw(struct iio_channel *chan, int val); > */ > int iio_read_max_channel_raw(struct iio_channel *chan, int *val); > > +/** > + * iio_read_min_channel_raw() - read minimum available raw value from a given > + * channel, i.e. the minimum possible value. > + * @chan: The channel being queried. > + * @val: Value read back. > + * > + * Note, if standard units are required, raw reads from iio channels > + * need the offset (default 0) and scale (default 1) to be applied > + * as (raw + offset) * scale. > + */ > +int iio_read_min_channel_raw(struct iio_channel *chan, int *val); > + > /** > * iio_read_avail_channel_raw() - read available raw values from a given channel > * @chan: The channel being queried.
diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c index 19ddd77adb11..7a1f6713318a 100644 --- a/drivers/iio/inkern.c +++ b/drivers/iio/inkern.c @@ -909,6 +909,69 @@ int iio_read_max_channel_raw(struct iio_channel *chan, int *val) } 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); diff --git a/include/linux/iio/consumer.h b/include/linux/iio/consumer.h index f536820b9cf2..e9910b41d48e 100644 --- a/include/linux/iio/consumer.h +++ b/include/linux/iio/consumer.h @@ -301,6 +301,18 @@ int iio_write_channel_raw(struct iio_channel *chan, int val); */ int iio_read_max_channel_raw(struct iio_channel *chan, int *val); +/** + * iio_read_min_channel_raw() - read minimum available raw value from a given + * channel, i.e. the minimum possible value. + * @chan: The channel being queried. + * @val: Value read back. + * + * Note, if standard units are required, raw reads from iio channels + * need the offset (default 0) and scale (default 1) to be applied + * as (raw + offset) * scale. + */ +int iio_read_min_channel_raw(struct iio_channel *chan, int *val); + /** * iio_read_avail_channel_raw() - read available raw values from a given channel * @chan: The channel being queried.