]> git.karo-electronics.de Git - linux-beck.git/commitdiff
iio: inkern: add helpers to query available values from channels
authorPeter Rosin <peda@axentia.se>
Tue, 8 Nov 2016 11:58:52 +0000 (12:58 +0100)
committerJonathan Cameron <jic23@kernel.org>
Sun, 13 Nov 2016 11:40:26 +0000 (11:40 +0000)
Specifically a helper for reading the available maximum raw value of a
channel and a helper for forwarding read_avail requests for raw values
from one iio driver to an iio channel that is consumed.

These rather specific helpers are in turn built with generic helpers
making it easy to build more helpers for available values as needed.

Signed-off-by: Peter Rosin <peda@axentia.se>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>
drivers/iio/inkern.c
include/linux/iio/consumer.h
include/linux/iio/iio.h

index 29df1157285857333f38c61d8c2a6b96c5c0a0e7..b0f4630a163f33cea23fad9c070babbb4d23c0e9 100644 (file)
@@ -716,6 +716,110 @@ int iio_read_channel_scale(struct iio_channel *chan, int *val, int *val2)
 }
 EXPORT_SYMBOL_GPL(iio_read_channel_scale);
 
+static int iio_channel_read_avail(struct iio_channel *chan,
+                                 const int **vals, int *type, int *length,
+                                 enum iio_chan_info_enum info)
+{
+       if (!iio_channel_has_available(chan->channel, info))
+               return -EINVAL;
+
+       return chan->indio_dev->info->read_avail(chan->indio_dev, chan->channel,
+                                                vals, type, length, info);
+}
+
+int iio_read_avail_channel_raw(struct iio_channel *chan,
+                              const int **vals, int *length)
+{
+       int ret;
+       int type;
+
+       mutex_lock(&chan->indio_dev->info_exist_lock);
+       if (!chan->indio_dev->info) {
+               ret = -ENODEV;
+               goto err_unlock;
+       }
+
+       ret = iio_channel_read_avail(chan,
+                                    vals, &type, length, IIO_CHAN_INFO_RAW);
+err_unlock:
+       mutex_unlock(&chan->indio_dev->info_exist_lock);
+
+       if (ret >= 0 && type != IIO_VAL_INT) {
+               /* raw values are assumed to be IIO_VAL_INT */
+               ret = -EINVAL;
+               goto err_unlock;
+       }
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(iio_read_avail_channel_raw);
+
+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);
+       switch (ret) {
+       case IIO_AVAIL_RANGE:
+               switch (*type) {
+               case IIO_VAL_INT:
+                       *val = vals[2];
+                       break;
+               default:
+                       *val = vals[4];
+                       *val2 = vals[5];
+               }
+               return 0;
+
+       case IIO_AVAIL_LIST:
+               if (length <= 0)
+                       return -EINVAL;
+               switch (*type) {
+               case IIO_VAL_INT:
+                       *val = vals[--length];
+                       while (length) {
+                               if (vals[--length] > *val)
+                                       *val = vals[length];
+                       }
+                       break;
+               default:
+                       /* FIXME: learn about max for other iio values */
+                       return -EINVAL;
+               }
+               return 0;
+
+       default:
+               return ret;
+       }
+}
+
+int iio_read_max_channel_raw(struct iio_channel *chan, int *val)
+{
+       int ret;
+       int type;
+
+       mutex_lock(&chan->indio_dev->info_exist_lock);
+       if (!chan->indio_dev->info) {
+               ret = -ENODEV;
+               goto err_unlock;
+       }
+
+       ret = iio_channel_read_max(chan, val, NULL, &type, IIO_CHAN_INFO_RAW);
+err_unlock:
+       mutex_unlock(&chan->indio_dev->info_exist_lock);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(iio_read_max_channel_raw);
+
 int iio_get_channel_type(struct iio_channel *chan, enum iio_chan_type *type)
 {
        int ret = 0;
index 638157234357b5813394d0240c5823725056c747..47eeec3218b5e31c30ed4583271af6ee4aa225aa 100644 (file)
@@ -225,6 +225,34 @@ int iio_read_channel_processed(struct iio_channel *chan, int *val);
  */
 int iio_write_channel_raw(struct iio_channel *chan, int val);
 
+/**
+ * iio_read_max_channel_raw() - read maximum available raw value from a given
+ *                             channel, i.e. the maximum possible value.
+ * @chan:              The channel being queried.
+ * @val:               Value read back.
+ *
+ * Note raw reads from iio channels are in adc counts and hence
+ * scale will need to be applied if standard units are required.
+ */
+int iio_read_max_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.
+ * @vals:              Available values read back.
+ * @length:            Number of entries in vals.
+ *
+ * Returns an error code, IIO_AVAIL_RANGE or IIO_AVAIL_LIST.
+ *
+ * For ranges, three vals are always returned; min, step and max.
+ * For lists, all the possible values are enumerated.
+ *
+ * Note raw available values from iio channels are in adc counts and
+ * hence scale will need to be applied if standard units are required.
+ */
+int iio_read_avail_channel_raw(struct iio_channel *chan,
+                              const int **vals, int *length);
+
 /**
  * iio_get_channel_type() - get the type of a channel
  * @channel:           The channel being queried.
index 849d524645e802a63643cce76a942730f7cbb51e..3f5ea2e9a39eb4d1451eb27c647c91e3d05b030d 100644 (file)
@@ -315,6 +315,23 @@ static inline bool iio_channel_has_info(const struct iio_chan_spec *chan,
                (chan->info_mask_shared_by_all & BIT(type));
 }
 
+/**
+ * iio_channel_has_available() - Checks if a channel has an available attribute
+ * @chan: The channel to be queried
+ * @type: Type of the available attribute to be checked
+ *
+ * Returns true if the channel supports reporting available values for the
+ * given attribute type, false otherwise.
+ */
+static inline bool iio_channel_has_available(const struct iio_chan_spec *chan,
+                                            enum iio_chan_info_enum type)
+{
+       return (chan->info_mask_separate_available & BIT(type)) |
+               (chan->info_mask_shared_by_type_available & BIT(type)) |
+               (chan->info_mask_shared_by_dir_available & BIT(type)) |
+               (chan->info_mask_shared_by_all_available & BIT(type));
+}
+
 #define IIO_CHAN_SOFT_TIMESTAMP(_si) {                                 \
        .type = IIO_TIMESTAMP,                                          \
        .channel = -1,                                                  \